1. 程式人生 > >vue細枝末節總結

vue細枝末節總結

scrip 順序 增加 使用 基本 所在 函數 watch 基本數據

下面總結一下我們在使用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細枝末節總結