(三)vue:自定義組件上使用v-model

一.v-model是如何工作的

input, select, textarea等是我們常用的在應用中傳遞數據的途徑。在vue中我們可以通過v-model進行雙向數據綁定,下面看一個例子:

<div id="app1">
   <input type="text" v-model="message">
   <span>{{message}}</span>
</div>
<script>
   var app1 = new Vue({
        el:'#app1',
         data:{
             message:"Hello Vue"
         }
   });
</script>

打開瀏覽器,查看渲染結果。
在這裏插入圖片描述
更改文本內容,可以看到中的內容會跟隨變化。

其實vue在解釋v-model的時候會做一個轉化工作,實質是下面這樣:

<div id="app2">
   <input type="text" :value="message" @input="message = $event.target.value">
   <span>{{message}}</span>
</div>
<script>
   var app2 = new Vue({
        el:'#app2',
         data:{
             message:"Hello Vue"
         }
   });
</script>

通過input元素的value屬性,和input事件達到v-model的作用。

二.仿照v-model的實現方法,在自定義組件上實現v-model功能

瞭解了v-model的本質,我們可以在自定義組件上模擬v-model的功能。編輯代碼如下:

<div id="app3">
        <custom-input2 :inputValue="message" @input-change="message=$event.target.value" :value="message"></custom-input2>
        <span>{{message}}</span>
</div>
<script type="text/javascript">
	Vue.component('custom-input2', {
        props:{
            inputValue:String
        },
        template:`<input type="text" :value="inputValue" @input="$emit('input-change', $event)"/>`
    });
    var app3 = new Vue({
         el:'#app3',
         data:{
             message:'Hello Vue'
         }
     });
</script>

打開瀏覽器,查看渲染結果,並修改文本框中的值,可以看到我們的目的達到了:
在這裏插入圖片描述
但是這樣做法有點太麻煩,能不能利用v-model達到我們想要的結果呢,請繼續往下面看。

三.自定義組件應用v-model

先直接在自定義組件上使用v-model:

<div id="app4">
  <custom-input v-model="message"></custom-input>
  <span>{{message}}</span>
</div>
<script>
Vue.component('custom-input3',{
   props:{
        value:String
    },
});
var app3 = new Vue({
	el:'#app3',
	   data:{
	       message:'Hello Vue'
	   }
});
</script>

當然這肯定無法達到我們想要的結果,那應該怎麼實現呢,首先,要明確的是v-model接受一個value屬性和一個input屬性,先看下面一個例子:

    <div id="app">
        <basic-input :value="name" @input="name=$event"></basic-input>
        <p>
            <strong>Name:</strong> {{ name }}
        </p>
    </div>
     <script type="text/javascript">
	    const BasicInput = {
	        template: '<input v-model="content" @input="handleInput" />',
	        prop: ['value'],
	        data() {
	            return {
	                content: this.value
	            }
	        },
	        methods: {
	            handleInput(e) {
	                this.$emit('input', this.content)
	            }
	        }
	    }
	    new Vue({
	        el: '#app',
	        data: { name: '' },
	        components: { BasicInput }
	    })
    </script>

渲染結果:
在這裏插入圖片描述
上面代碼功能是我們想要的,但是basic-input還是沒有用到v-model,但是我們可以發現,它用到了value屬性和input事件,那麼我們只需要在使用組件的地方更改成如下代碼就可以了:

<basic-input v-model="name"></basic-input>

好,至此我們已經實現了在自定義組件上使用v-model的目的,但真的結束了嗎?通過上面的研究可以發現,v-model最終轉化爲value屬性和input事件來實現,這就限制了使用的範圍,怎麼使用我們自定義的事件和屬性呢,請繼續往下看。

四.使用自定義事件和屬性

vue組件爲我們提供了一個model屬性,這個屬性可以幫助我們達到使用自定義事件和屬性的目的,將代碼修改如下:

    <div id="app">
        <basic-input v-model="name"></basic-input>
        <p>
            <strong>Name:</strong> {{ name }}
        </p>
    </div>
    <script type="text/javascript">
    const BasicInput = {
        template: '<input v-model="content" @input="handleInput" />',
        prop: ['new-value'],
        model:{
          event:'input-change',
          prop:'new-value'
        },
        data() {
            return {
                content: this.new-value
            }
        },
        methods: {
            handleInput(e) {
                this.$emit('input-change', this.content)
            }
        }
    }

    new Vue({
        el: '#app',
        data: { name: '' },
        components: { BasicInput }
    })
    </script>

vue在解析 <basic-input v-model="name"></basic-input>時,會將其轉化爲<basic-input :new-value=name @input-change="name=$event"></basic-input>.

以上就是我對v-model的理解,如有不對的地方,請在下方糾正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章