vue细枝末节总结

Posted kingsm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue细枝末节总结相关的知识,希望对你有一定的参考价值。

下面总结一下我们在使用vue过程中,经常会踩到坑却会被忽略的问题:

1、vue data中声明了某个属性,有些时候却发现该属性没有发生响应式变更
问题描述:在data中声明了某个属性,后面给该属性赋值,正常逻辑下与该属性绑定的UI会发生响应。但是由于代码编写失误,会造成UI不发生响应的情况。
发生这个问题需要了解vue的响应式原理,vue使用Object.defineProperty进行响应式操作。初始化data数据的时候,vue会递归地遍历声明过得data属性,对该属性的每一个子属性都应用Object.property发放进行响应式绑定。如果当这个属性或者属性中的某一个子属性发生内存引用的改变或者基本数据类型的变更时。就会触发对应的响应式函数,在对应的响应式函数中可以修改UI,最终达到响应式效果。
问题是,当我们第一次修改了整个属性的内存指向时,当新的内存中不存在最初声明的子属性时,与子属性发生绑定的UI就无法再次发生响应。这就是问题所在。
vue官方给出了定义单个属性的方式,组件内的用法如下:
    // ...
    methods: {
      change () {
        this.$set(obj, ‘property‘, value)
        // 通过以上方式可以给obj对象的property属性设置value值,并且会重新发生响应式绑定
      }
    }
    // ...
需要注意的是:vue中只有被声明的属性发生引用改变或者基本数据类型的变动时,才能出发响应式操作。实例如下:
    // ...
    data: {
      obj1: {
        pro1: ‘‘
      }
    }
    // ...
2、watch 和 事件的执行先后顺序
在vue中,对同一个属性使用 watch 和 input 事件进行监听变化。我们通过实例会发现,input事件的触发是在 watch之前发生的。示例如下:
    <div>
        <input v-model="msg" @input="inputHandle" />
      </div>

      // js
      data: {
        msg: ‘‘
      },
      methods: {
        inputHandle () {
          // 事件触发
          // 触发比较早
        }
      },
      watch: {
        msg (newVal, oldVal) {
          // watch 触发
          // 触发比较晚
        }
      }
3、computed 属性 发生赋值操作
vue的计算属性,我们常用的其实是一种简写形式,如下:
    data: {
        msg: ‘‘
      },
      computed: {
        cmsg () {
          return this.msg + ‘ computed‘
        }
      }
其实上面是一种简写形式,我们补全其完整形式,如下:
    data: {
        msg: ‘‘
      },
      computed: {
        cmsg: {
          get () {
            return this.msg + ‘ computed‘
          }
        }
      }
上面两段代码的作用是完全一样的,通常我们采用上面的写法。但是下面的写法有独特的应用场景,如果我们需要对计算属性进行赋值操作,或者是对计算属性进行赋值操作时的控制,我们可以对该计算属性进行set函数的自定义。如下:
    data: {
        msg: ‘‘
      },
      computed: {
        cmsg: {
          get () {
            return this.msg + ‘ computed‘
          },
          set (newVal) {
            // ...
            // 此处我们可以编写自己的业务代码
          }
        }
      },
      methods: {
        changeCmsg () {
          this.cmsg = ‘hello‘
          // 此处会对 cmgs这个计算属性进行赋值,这时候会触发set函数。
        }
      }
4、v-model 是 v-bind:value 和 v-on:input 的语法糖,有时候需要拆开使用
在vue1.x版本中可以对 v-model使用过滤器,而在vue2.x版本中取消了这个功能,我们要实现这个功能可以通过 将 v-model 拆分为 v-bind:value 和 v-on:input 的形式来完成这个功能:
    <template>
      <input v-bind:value="msg" v-on:input="inputHandle($event)" />
    </template>

    <script>
      new Vue({
        data: {
          msg: ‘‘,
          realMsg: ‘‘
        },
        methods: {
          inputHandle (e) {
            // 给展示的数据增加 过滤效果
            this.msg = filter(e.target.value)
            // 给真实数据取消过滤效果
            this.realMsg = deFilter(e.target.value)
          }
        }
      })
    </script>
5、自定义组件需要使用v-model指令
自定义组件上使用的原理也是利用了 v-model的本质,将v-model拆分为 v-bind:value 和 v-on:input 的形式,具体示例如下:
    // 注册组件
    Vue.component(‘my-com‘, {
      template: `
        <div>
          <input type="text" v-model="model" />
        </div>
      `,
      data () {
        return {
          model: ‘‘
        }
      },
      props: [‘value‘],
      watch: {
        value (newVal, oldVal) {
          this.model = newVal
        },
        model (newVal, oldVal) {
          this.$emit(‘input‘, newVal)
        }
      }
    })

    // template
    <my-com v-model="childMsg"></my-com>
6、watch的函数形式
    created () {
      this.$watch(() => this.model[this.data.prop], (newVal, oldVal) => {
          // ...
        })
    }
被watch的属性可以是一个函数的返回值,在函数执行时会求解 返回的表达式的值
7、vue组件中的data需要使用函数返回值的形式的解释
    data () {
      return {
        // ... your data
      }
    }
原因:我们使用组件的目的是为了充分地复用,也就是说声明的组件是会被很多父组件所引用的,在js中对象类型的数据是引用类型,为了防止在多个父组件中修改同一个data 所指向的内存空间,我们必须给每一个父组件所引用的组件一个单独的data对象。而函数的返回值恰恰可以做到这点。
 

以上是关于vue细枝末节总结的主要内容,如果未能解决你的问题,请参考以下文章

回归 | js实用代码片段的封装与总结(持续更新中...)

vue开发快捷键的总结

VSCode自定义代码片段1——vue主模板

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段(vue主模板)

VSCode自定义代码片段11——vue路由的配置