vue原生input輸入框原理剖析

正文

首先我們來看一段代碼:

<input value="value">

這裡是一個原生的input輸入框,每一個原生的輸入框都會有一個value的屬性來用於存儲用於輸入的最新的數據。

如果我們想要獲取到這個值我們可以通過input.target.value或者通過$event.target.value來獲取這個存儲的值。

隻要用戶輸入瞭數據,那麼此時input標簽就會將輸入的數據放到這個value中(新數據會覆蓋舊數據,所以我們獲取到的都是最新的)。

現在我們來看上面的標簽,我們為input標簽添加瞭一個value屬性,並且賦值'value'。其實在標簽上設置value屬性它的作用有兩個:

  • 在第一次創建input標簽的時候,將對應的初始值展示到輸入框中 (在無該屬性使輸入框不展示任何數據)
  • 使用value屬性的初始值來初始化input.target.value(無該屬性時input.target.value為空串)

上面的那段代碼的意思是通過添加value="value"屬性,初始化input.target.value的值並且將初始值展示到對應的輸入框中

這裡需要註明一點,在後續用戶輸入的操作中,輸入框中的數據隻是方便讓用戶看到自己輸入瞭什麼僅此而已。 有人可以會有疑問,難道不是input.target.value裡是什麼所以輸入框內就顯示什麼嗎?其實不是的。

輸入框顯示什麼和 input.target.value並沒有直接聯系,輸入框內的顯示隻是方便用戶自己看到自己輸入瞭什麼。

小結:

input中的value有兩種:value="xxx"input.target.value 我們需要知道兩個分別有什麼作用。在整個輸入顯示流程中, 他們分別扮演什麼角色。

現在我們來看在vue中的輸入框,首先我們來看一段代碼:

<input
   v-bind:value
   @input="value = $event.target.value"
/>
data(){
    return {
          value:'123'
    }
}

我們一般使用v-bind:value來給Input標簽綁定一個vue中的的,這裡我們綁定的是this.value。 在這裡v-bind:value === :value="value"。 這樣實現的原理比較簡單。

首先我們定義瞭this.value因為將this.value綁定到瞭:value上,所以初始時會在輸入框展示我們指定的 值,即'123'。當我們輸入數據之後,此時$envet.target.value(這裡的$event.target.value就是input.target.value)就會存儲我們最新的輸入的值,然後將最新的值賦值給this.value

因為this.value變化瞭,此時vue對頁面進行更新,此時更新後的input:value是最新值。

但是這裡有一個問題,那就是<input>並不會被銷毀重建,也就是說this.value = $event.target.value隻是改變瞭this.value 若別的地方引用瞭this.value,那麼就會同步改變。那麼this.value的更新對:value="value"的影響是什麼呢?其實沒有什麼影響。

因為我們前面說瞭,:value的作用有兩個:一是初始化input.value的值,二是將初始值渲染到對應的輸入框中。 在一開始將this.value作為初始值給Input.value和展示在框裡,他的任務已經完成瞭,後續的更改對:value沒有一點關系。

其實:value="value"的唯一作用就是將this.value作為初始值綁定和展示到input上。

v-model

現在對於原始元素進行算雙向數據綁定已經完成。那麼如何實現父組件和子組件之間的雙向數據綁定嗯? 此時我們需要在子組件中使用v-model。 關於 v-model 的使用這裡不再贅述。這裡隻討論如何在自定義組件實現 v-model。根據vue 的官網的描述,我們大概知道,v-model 的本質就是語法糖,即:

<input type="text" v-model="name">
相當於:
<input type="text" :value="name" @input="name = $event.target.value">

vue監聽輸入框輸入行為然後改變對應的值。 如果對子組件進行雙向數據綁定該如何實現呢?這裡的雙向數據綁定指的是父組件將值傳遞給子組件使用,並且子組件可以改變父組件的值 其實上述的雙向綁定可以通過v-bind:propName.sync = 'xxx'來實現。 除瞭以上的方式,並且Vue還給我們提供瞭另一種方式:

<!-- 父組件.vue -->
<child-component :propName="data" @change="change" />
export default {
    data(){
     data:'123'
  },
  methods:{
     change(value){
        this.data = value
     }
  }
}
//在組件中如何想要改變父組件的值,那麼直接出發對應的事件即可:
this.$emit('change', newValue )

vue中,它將上述的方法進行瞭簡化,我們可以使用v-model來對子組件進行雙向數據綁定。例如:

<child-component v-model="pageTitle" />
<!-- 是以下的簡寫: -->
<child-component :value="pageTitle" @input="pageTitle = $event" /> 

在默認情況下v-model的觸發事件名稱為input。 子組件想要使用的話,需要定義一個名為valueprop才能使用。 而在子組件中更改該值,隻需要定義一個函數,有必要的時候執行 this.$emit('input', newValue) 即可。

這裡的newValue就是$event。 這樣就可以改變對應的值。 當然除瞭默認的valueinput的命名,vue還給我們提過瞭更加靈活的方式。

<!-- 父組件 -->
<child-component v-model="pageTitle" />
//子組件
export default {
  model: {
    prop: 'title', //這裡相當於別名,這裡可以起其他名稱
    event: 'change' //這裡相當於事件的別名,這裡可以起其他名稱
  },
  props: {
    // 這將允許 `value` 屬性用於其他用途
    value: String,
    // 使用 `title` 代替 `value` 作為 model 的 prop
    title: {
      type: String,
      default: 'Default title'
    }
  }
}

當我們想在子組件中改變傳入的值,那麼直接可以this.$emit('change', newValue)

所以,在這個例子中 v-model 是以下的簡寫:

<child-component :title="pageTitle" @change="pageTitle = $event" />

其實本質上,項目中的twowayFactor這個混入配置類,他本質上就是做瞭上面的操作。

  @Prop()
  @Model('valueChanged')
      bindValue!: T;

這樣做的目的是將v-model傳入的prop改為bindValue。 然後將默認事件的名稱從input改為瞭valueChange。 接著設置get/set

        get currentValue() {
            return this.bindValue;
        }
        set currentValue(value) {
            this.$emit('valueChanged', value);
        }

這樣做的目的是數據本地化。 在組件內部定義一個currentValue 然後為該值設置get,當訪問currentValue等價於訪問v-modelprop。 然後設置set。當改變currentValue的值時,此時就會觸發對應的事件。 當觸發之後父組件中的值就會變化。這就實現瞭雙向數據綁定。

我們可以看到,其實this.currentValue的作用就是v-model操作的語法糖。 它並沒有什麼特別之處,隻是將v-model傳入的數據的訪問和更改簡單化瞭,都集中與一個值this.currentValue

以上就是vue原生input輸入框原理剖析的詳細內容,更多關於vue原生input輸入框的資料請關註WalkonNet其它相關文章!

推薦閱讀: