项目需求 后台表单是前台自建的 控件自然也要自建 自然就有各种选项

其中选择框 就有单选多选选项 项目使用的element-ui 自然就用的el-select

由于数据库并没有类似数组的字段 选择框使用varchar 而el-select多选时却需要使用数组 所以在编辑时 需要将值转成数组再赋值给el-select的value 

<template>
  <el-select
    :value="data"
    @change="val => $emit('input', String(val))"
    :disabled="control.disabled == '1'"
    :multiple="control.multiple == '1'"
    :allow-create="control.allow_create == '1'"
    :style="css"
    :size="size"
    filterable
    default-first-option
    clearable
  >
    <el-option
      v-for="option in options"
      :key="option.value"
      :label="option.label"
      :value="option.value">
      <slot :option="option"></slot>
      <!-- <component v-if="slotsEx" :is="slotsEx" :option="option"></component> -->
    </el-option>
  </el-select>
</template>

<script>
export default {
  computed:{
    data(){
      if(this.control.multiple == '1' && this.value && this.value.split){
        return this.value.split(',')
      }else{
        if(this.control.multiple  == '1'){
          return []
        }else{
          return this.value
        }
      }
    }
  }
}
</script>

data根据控件属性 control.multiple 动态计算

由于我们的数组数据是使用逗号分隔符 所以直接使用String可以提交数据就可以 单选多选的时候 都可以提交正确的数据

单独使用的时候 多选单选都没有问题 但是由于配置的时候 需要实时切换 切换的时候 就报了错

errorLog.js:17 TypeError: Cannot read property 'value' of undefined
    at VueComponent.getValueKey (index.js:1)
    at Proxy.boundFn (vue.esm.js:188)
    at index.js:1
    at Proxy.renderList (vue.esm.js:3673)
    at Proxy.n (index.js:1)
    at VueComponent.Vue._render (vue.esm.js:4437)
    at VueComponent.updateComponent (vue.esm.js:2755)
    at Watcher.get (vue.esm.js:3105)
    at Watcher.run (vue.esm.js:3182)
    at flushSchedulerQueue (vue.esm.js:2944) "render"

错误栈都在Vue内部  

查看el-select源码(element\packages\select\src\select.vue )后 推测应该是触发multiple更改后value值还未计算 select已经开始响应渲染 而此时value值还未被计算成数组 导致内部出错

查看官方文档后并未发现有multiple动态更改的方法,也不好大改el-select控件 随后想到可以在更改multiple后重新渲染组件

查看官方文档  可使用 $forceUpdate  强制更新组件 

使用后发现 效果并不理想 原因 $forceUpdate  只能控制重渲染 并不能控制渲染过程

 

虽然该错误并不多影响实际使用 一个好的猴子不能就此放弃

随后想到可以使用v-if控制渲染 在multiple改变时停止渲染 待value计算完毕后重新渲染组件 

由于javascript是队列机制 可以使用setTimeout 将函数推至队列末尾 即可实现value计算后重新渲染组件

由于只有在编辑控件的时候 才会触发重新渲染 所以在实际使用中并不会触发 不会有性能问题

<el-select
    v-if="update"
    ...more
  ></el-select>
<script>
{
  data(){
    return {
      update: true
    }
  },
  watch:{
    'control.multiple'(){
      this.update = false
      setTimeout(()=>{
        this.update = true
      })
    }
  }
}
</script>

完美解决 

总结 

善用setTimeout 0  遇到解决不了的问题 可以通过翻阅文档、源码、另辟蹊径等方法解决

GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:2 个月前 )
c345bb45 6 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐