半个闲人 發表於 2025-8-21 11:43:00

在Vue3+ElementPlus前端中,使用watch监控对象变化,实现字典列表的级联更新处理

<p>在Vue3+ElementPlus前端中,有时候一些字典的关联显示,需要使用级联,因此一般使用watch监控对象变化,实现字典列表的级联更新。本篇随笔介绍基于实际案例来实现多级关联的处理操作,以供参考。</p>
<h3>1、省市区的级联案例</h3>
<p>在很多实际业务项目中,往往都可能涉及到级联显示的场景。比如有 <strong data-start="58" data-end="76">省份 -&gt; 城市 -&gt; 区县</strong> 的字典数据,用户在选择“省份”时,自动更新“城市”选项;选择“城市”时,自动更新“区县”选项。基本的处理过程如下所示。</p>
<ul>
<li data-start="145" data-end="184">
<p data-start="147" data-end="184">使用 <strong data-start="150" data-end="170"><code data-start="152" data-end="157">ref</code>/<code data-start="158" data-end="168">reactive</code></strong> 保存选择值和字典数据。</p>
</li>
<li data-start="185" data-end="224">
<p data-start="187" data-end="224">使用 <strong data-start="190" data-end="201"><code data-start="192" data-end="199">watch</code></strong> 监听上级字段变化,动态更新下级字典数据。</p>
</li>
<li data-start="225" data-end="252">
<p data-start="227" data-end="252">下级值要 <strong data-start="232" data-end="241">清空/重置</strong>,避免残留无效值。</p>
</li>
</ul>
<p>对于省市区简单例子的Vue3模板界面,如下代码所示。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">template</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>省份:<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">v-model</span><span style="color: rgba(0, 0, 255, 1)">="province"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">option </span><span style="color: rgba(255, 0, 0, 1)">:value</span><span style="color: rgba(0, 0, 255, 1)">="null"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>请选择<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">option</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">option </span><span style="color: rgba(255, 0, 0, 1)">v-for</span><span style="color: rgba(0, 0, 255, 1)">="p in provinces"</span><span style="color: rgba(255, 0, 0, 1)"> :key</span><span style="color: rgba(0, 0, 255, 1)">="p.code"</span><span style="color: rgba(255, 0, 0, 1)"> :value</span><span style="color: rgba(0, 0, 255, 1)">="p.code"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ p.name }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">option</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>城市:<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">v-model</span><span style="color: rgba(0, 0, 255, 1)">="city"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">option </span><span style="color: rgba(255, 0, 0, 1)">:value</span><span style="color: rgba(0, 0, 255, 1)">="null"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>请选择<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">option</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">option </span><span style="color: rgba(255, 0, 0, 1)">v-for</span><span style="color: rgba(0, 0, 255, 1)">="c in cities"</span><span style="color: rgba(255, 0, 0, 1)"> :key</span><span style="color: rgba(0, 0, 255, 1)">="c.code"</span><span style="color: rgba(255, 0, 0, 1)"> :value</span><span style="color: rgba(0, 0, 255, 1)">="c.code"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ c.name }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">option</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>区县:<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">v-model</span><span style="color: rgba(0, 0, 255, 1)">="area"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">option </span><span style="color: rgba(255, 0, 0, 1)">:value</span><span style="color: rgba(0, 0, 255, 1)">="null"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>请选择<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">option</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">option </span><span style="color: rgba(255, 0, 0, 1)">v-for</span><span style="color: rgba(0, 0, 255, 1)">="a in areas"</span><span style="color: rgba(255, 0, 0, 1)"> :key</span><span style="color: rgba(0, 0, 255, 1)">="a.code"</span><span style="color: rgba(255, 0, 0, 1)"> :value</span><span style="color: rgba(0, 0, 255, 1)">="a.code"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ a.name }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">option</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">template</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>在其script脚本代码的操作中,使用watch来处理界面代码逻辑如下所示。</p>
<div class="cnblogs_code">
<pre>&lt;script setup lang="ts"&gt;<span style="color: rgba(0, 0, 0, 1)">
import { ref, watch } from </span>'vue'

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 模拟字典数据</span>
const provinces =<span style="color: rgba(0, 0, 0, 1)"> ref([
{ code: </span>'gd', name: '广东'<span style="color: rgba(0, 0, 0, 1)"> },
{ code: </span>'bj', name: '北京'<span style="color: rgba(0, 0, 0, 1)"> }
])

const citiesDict: Record</span>&lt;string, { code: string; name: string }[]&gt; =<span style="color: rgba(0, 0, 0, 1)"> {
gd: [
    { code: </span>'gz', name: '广州'<span style="color: rgba(0, 0, 0, 1)"> },
    { code: </span>'sz', name: '深圳'<span style="color: rgba(0, 0, 0, 1)"> }
],
bj: [
    { code: </span>'dc', name: '东城'<span style="color: rgba(0, 0, 0, 1)"> },
    { code: </span>'xc', name: '西城'<span style="color: rgba(0, 0, 0, 1)"> }
]
}

const areasDict: Record</span>&lt;string, { code: string; name: string }[]&gt; =<span style="color: rgba(0, 0, 0, 1)"> {
gz: [{ code: </span>'tianhe', name: '天河区' }, { code: 'yuexiu', name: '越秀区'<span style="color: rgba(0, 0, 0, 1)"> }],
sz: [{ code: </span>'nanshan', name: '南山区' }, { code: 'futian', name: '福田区'<span style="color: rgba(0, 0, 0, 1)"> }],
dc: [{ code: </span>'xx', name: '东城区示例'<span style="color: rgba(0, 0, 0, 1)"> }],
xc: [{ code: </span>'yy', name: '西城区示例'<span style="color: rgba(0, 0, 0, 1)"> }]
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当前选择</span>
const province = ref&lt;string | <span style="color: rgba(0, 0, 255, 1)">null</span>&gt;(<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
const city </span>= ref&lt;string | <span style="color: rgba(0, 0, 255, 1)">null</span>&gt;(<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
const area </span>= ref&lt;string | <span style="color: rgba(0, 0, 255, 1)">null</span>&gt;(<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 下级字典</span>
const cities = ref&lt;{ code: string; name: string }[]&gt;<span style="color: rgba(0, 0, 0, 1)">([])
const areas </span>= ref&lt;{ code: string; name: string }[]&gt;<span style="color: rgba(0, 0, 0, 1)">([])

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 监听省份变化 → 更新城市</span>
<span style="color: rgba(255, 0, 0, 1)"><strong>watch(province, (newVal)</strong></span> =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (newVal) {
    cities.value </span>= citiesDict ||<span style="color: rgba(0, 0, 0, 1)"> []
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
    cities.value </span>=<span style="color: rgba(0, 0, 0, 1)"> []
}
city.value </span>= <span style="color: rgba(0, 0, 255, 1)">null</span>   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 清空下级选择</span>
area.value = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
areas.value </span>=<span style="color: rgba(0, 0, 0, 1)"> []
})

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 监听城市变化 → 更新区县</span>
<span style="color: rgba(255, 0, 0, 1)"><strong>watch(city, (newVal)</strong> </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (newVal) {
    areas.value </span>= areasDict ||<span style="color: rgba(0, 0, 0, 1)"> []
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
    areas.value </span>=<span style="color: rgba(0, 0, 0, 1)"> []
}
area.value </span>= <span style="color: rgba(0, 0, 255, 1)">null</span>   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 清空下级选择</span>
<span style="color: rgba(0, 0, 0, 1)">})
</span>&lt;/script&gt;</pre>
</div>
<p>有时候,对于字段的处理顺序,我们可能需要引入nextick来处理。</p>
<p><code data-start="7" data-end="17">nextTick</code> 在 Vue3 里非常适合用来 <strong data-start="33" data-end="56">等 DOM 和响应式更新完成再执行逻辑</strong>。<br data-start="57" data-end="60">
在「编辑场景级联字典」这种情况里,<code data-start="77" data-end="87">nextTick</code> 可以解决 <strong data-start="93" data-end="112">字典更新和已有值赋值的时序问题</strong>。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 监听省份变化 → 更新城市字典</span>
<span style="color: rgba(0, 0, 0, 1)">watch(
() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> form.province,
async (newVal) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">newVal) {
      cities.value </span>=<span style="color: rgba(0, 0, 0, 1)"> []
      form.city </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
      form.area </span>= <span style="color: rgba(0, 0, 255, 1)">null</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">
    }

    cities.value </span>=<span style="color: rgba(0, 0, 0, 1)"> await fetchCities(newVal)

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ⚡ 用 nextTick 等 cities 更新后再校验</span>
<span style="color: rgba(0, 0, 0, 1)">    await nextTick()
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!cities.value.find(c =&gt; c.code ===<span style="color: rgba(0, 0, 0, 1)"> form.city)) {
      form.city </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
      form.area </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
    }
},
{ immediate: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> }
)</span></pre>
</div>
<p>&nbsp;</p>
<h3>2、电力记录业务的处理案例</h3>
<p>在我们的一个项目案例中,对于电力的一些级联处理,也有类似的参考价值,如对于电力记录的处理中,我们需要根据地区进行一级、二级、三级能耗的下拉列表级联更新,方便在录入的时候进行关联显示。下面是数据列表的显示部分界面截图。</p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202508/8867-20250821112956148-1126564805.png" alt="image" width="506" height="246" loading="lazy"></p>
<p>&nbsp;在数据编辑或者新增的情况下,我们需要根据这些内容进行级联的显示处理,那么界面如下所示。</p>
<p>&nbsp;</p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202508/8867-20250821113237007-1577214700.png" alt="image" width="533" height="189" loading="lazy"></p>
<p>我们看到,以上几个了下拉列表的字典内容,都存在一定的级联关系,如选择区域后,需要更新一级列表、选择一级列表后,需要更新二级列表、选择二级列表后,需要更新三级列表等等。</p>
<p>我们使用watch来跟踪对象的变化,并及时进行字典数据的更新,如下逻辑代码所示。</p>
<div class="cnblogs_code">
<pre>const area = ref([]); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 能源区域</span>
const level1 = ref([]); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一级能耗计量</span>
const level2 = ref([]); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 二级能耗计量</span>
const level3 = ref([]); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 三级能耗计量</span>
const <span style="color: rgba(255, 0, 0, 1)"><strong>initArea</strong> </span>= () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
electrecord.GetFieldDict(</span>'area').then(data =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(data);</span>
    area.value =<span style="color: rgba(0, 0, 0, 1)"> data;
});
};

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断下拉框的值是否有改变</span>
<span style="color: rgba(0, 0, 0, 1)">watch(
() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> editForm.area,
(newValue) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">newValue) {
      editForm.level1 </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.level2 </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.level3 </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (newValue) {
      const whereStr </span>= `area='${newValue}'<span style="color: rgba(0, 0, 0, 1)">`;
      electmerter.GetFieldDict(</span>'level1', whereStr).then(data =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(data);</span>
      level1.value =<span style="color: rgba(0, 0, 0, 1)"> data;
      });
    }
},
{ immediate: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> }
);

watch(
() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> editForm.level1,
(newValue) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">newValue) {
      editForm.level2 </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.level3 </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.devicename </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.devicecode </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.lastnumber </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (newValue) {
      const whereStr </span>= `level1='${newValue}' and area='${editForm.area}'<span style="color: rgba(0, 0, 0, 1)">`;
      <span style="color: rgba(255, 0, 0, 1)"><strong>electmerter.GetFieldDict</strong></span>(</span>'level2', whereStr).then(data =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(data);</span>
      level2.value =<span style="color: rgba(0, 0, 0, 1)"> data;
      });
    }
},
{ immediate: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> }
);
watch(
() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> editForm.level2,
(newValue) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">newValue) {
      editForm.level3 </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.devicename </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.devicecode </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.lastnumber </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (newValue) {
      const whereStr </span>= `level2='${newValue}' and area='${editForm.area}' and level1='${editForm.level1}'<span style="color: rgba(0, 0, 0, 1)">`;
      electmerter.GetFieldDict(</span>'level3', whereStr).then(data =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(data);</span>
      level3.value =<span style="color: rgba(0, 0, 0, 1)"> data;
      });
    }
},
{ immediate: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> }
);
watch(
() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> editForm.level3,
(newValue) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">newValue) {
      editForm.devicename </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.devicecode </span>= ''<span style="color: rgba(0, 0, 0, 1)">;
      editForm.lastnumber </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
    }
},
{ immediate: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> }
);</span></pre>
</div>
<p>其中&nbsp;electmerter.GetFieldDict 是ES6类中的API调用函数,主要对标后端代码里面,通用处理的获取对应表的关联字段列表。</p>
<p>后端通用的处理代码如下C#代码所示。</p>
<div class="cnblogs_code">
<pre>      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 根据字段名称,获取对应的字典列表
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="fieldName"&gt;</span><span style="color: rgba(0, 128, 0, 1)">字段名称</span><span style="color: rgba(128, 128, 128, 1)">&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="whereStr"&gt;</span><span style="color: rgba(0, 128, 0, 1)">条件字符串,如Age &gt; 20 AND IsActive = true</span><span style="color: rgba(128, 128, 128, 1)">&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task&lt;List&lt;CListItem&gt;&gt; GetFieldDict(<span style="color: rgba(0, 0, 255, 1)">string</span> fieldName, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> whereStr)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> list = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;CListItem&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">fieldName.IsNullOrEmpty())
            {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">var sql = $"Select distinct {fieldName} from Table";</span>
                <span style="color: rgba(0, 0, 255, 1)">var</span> query = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.EntityDb.AsQueryable();
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.IsNullOrWhiteSpace(whereStr))
                {
                  query </span>=<span style="color: rgba(0, 0, 0, 1)"> query.Where(whereStr);
                }

                </span><span style="color: rgba(0, 0, 255, 1)">var</span> fieldList = <span style="color: rgba(0, 0, 255, 1)">await</span> query.Distinct().Select&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)">(fieldName).ToListAsync();
                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(fieldList != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; fieldList.Count &gt;<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">var</span> sortedList =<span style="color: rgba(0, 0, 0, 1)"> fieldList
                        .OrderBy(name </span>=&gt; GetSortIndex(name))<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主排序:数字前缀</span>
                        .ThenBy(name =&gt; name)                <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 次排序:中文拼音顺序</span>
<span style="color: rgba(0, 0, 0, 1)">                        .ToList();
                  list </span>= sortedList.Select(s =&gt; <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CListItem(s)).ToList();
                }
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> list;
      }</span></pre>
</div>
<p>以上就是一些简单案例上对于watch的使用,用于处理多级关联更新的情况下的功能实现。</p>

</div>
<div id="MySignature" role="contentinfo">
    <div style="border-right-color: #cccccc; border-right-width: 1px; border-right-style: solid; padding-right: 5px; border-top-color: #cccccc; border-top-width: 1px; border-top-style: solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; border-left-width: 1px; border-left-style: solid; width: 98%; padding-top: 4px; border-bottom-color: #cccccc; border-bottom-width: 1px; border-bottom-style: solid; background-color: #eeeeee;">
    <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" alt>
    <span style="color: #000000"><span class="Apple-tab-span" style="white-space: pre"></span>
   专注于代码生成工具、.Net/Python 框架架构及软件开发,以及各种Vue.js的前端技术应用。著有Winform开发框架/混合式开发框架、微信开发框架、Bootstrap开发框架、ABP开发框架、SqlSugar开发框架、Python开发框架等框架产品。
   <br>  转载请注明出处:撰写人:伍华聪  http://www.iqidi.com <br>    </span></div><br><br>
来源:https://www.cnblogs.com/wuhuacong/p/19050425
頁: [1]
查看完整版本: 在Vue3+ElementPlus前端中,使用watch监控对象变化,实现字典列表的级联更新处理