真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

揭密Vue的雙向綁定-創(chuàng)新互聯(lián)

Vue 中需要輸入什么內(nèi)容的時(shí)候,自然會(huì)想到使用 <input v-model="xxx" /> 的方式來實(shí)現(xiàn)雙向綁定。下面是一個(gè)最簡(jiǎn)單的示例

撫寧網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)成立于2013年到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。

What's your name:

Hello {{ name }}
new Vue({
    el: "#app",
    data: {
        name: ""
    }
});

JsFiddle 演示

https://jsfiddle.net/0okxhc6f/

在這個(gè)示例的輸入框中輸入的內(nèi)容,會(huì)隨后呈現(xiàn)出來。這是 Vue 原生對(duì) <input> 的良好支持,也是一個(gè)父組件和子組件之間進(jìn)行雙向數(shù)據(jù)傳遞的典型示例。不過 v-model 是 Vue 2.2.0 才加入的一個(gè)新功能,在此之前,Vue 只支持單向數(shù)據(jù)流。

Vue 的單向數(shù)據(jù)流

Vue 的單向數(shù)據(jù)流和 React 相似,父組件可以通過設(shè)置子組件的屬性(Props)來向子組件傳遞數(shù)據(jù),而父組件想獲得子組件的數(shù)據(jù),得向子組件注冊(cè)事件,在子組件高興的時(shí)候觸發(fā)這個(gè)事件把數(shù)據(jù)傳遞出來。一句話總結(jié)起來就是,Props 向下傳遞數(shù)據(jù),事件向上傳遞數(shù)據(jù)。

上面那個(gè)例子,如果不使用 v-model,它應(yīng)該是這樣的

由于事件處理寫成了內(nèi)聯(lián)模式,所以腳本部分不需要修改。但是多數(shù)情況下,事件一般都會(huì)定義成一個(gè)方法,代碼就會(huì)復(fù)雜得多

new Vue({
    // ....
    methods: {
        updateName(e) {
            this.name = e.target.value;
        }
    }
})

從上面的示例來看 v-model 節(jié)約了不少代碼,最重要的是可以少定義一個(gè)事件處理函數(shù)。所以 v-model 實(shí)際干的事件包括

  • 使用 v-bind(即 :)單向綁定一個(gè)屬性(示例::value="name"
  • 綁定 input 事件(即 @input)到一個(gè)默認(rèn)實(shí)現(xiàn)的事件處理函數(shù)(示例:@input=updateName
  • 這個(gè)默認(rèn)的事件處理函數(shù)會(huì)根據(jù)事件對(duì)象帶入的值來修改被綁定的數(shù)據(jù)(示例:this.name = e.target.value

自定義組件的 v-model

Vue 對(duì)原生組件進(jìn)行了封裝,所以 <input> 在輸入的時(shí)候會(huì)觸發(fā) input 事件。但是自定義組件應(yīng)該怎么呢?這里不妨借助 JsFiddle Vue 樣板的 Todo List 示例。

JsFiddle 的 Vue 樣板

點(diǎn)擊 JsFilddle 的 Logo,在上面彈出面板中選擇 Vue 樣板即可

樣板代碼包含 HTML 和 Vue(js) 兩個(gè)部分,代碼如下:

Todos:

new Vue({
  el: "#app",
  data: {
    todos: [
      { text: "Learn JavaScript", done: false },
      { text: "Learn Vue", done: false },
      { text: "Play around in JSFiddle", done: true },
      { text: "Build something awesome", done: true }
    ]
  },
  methods: {
    toggle: function(todo){
        todo.done = !todo.done
    }
  }
})

定義 Todo 組件

JsFiddle 的 Vue 模板默認(rèn)實(shí)現(xiàn)一個(gè) Todo 列表的展示,數(shù)據(jù)是固定的,所有內(nèi)容在一個(gè)模板中完成。我們首先要做事情是把單個(gè) Todo 改成一個(gè)子組件。因?yàn)樵?JsFiddle 中不能寫成多文件的形式,所以組件使用 Vue.component() 在腳本中定義,主要是把 <li> 內(nèi)容中的那部分拎出來:

Vue.component("todo", {
    template: `

`,
    props: ["text", "done"],
    data() {
        return {
            isDone: this.done
        };
    },
    methods: {
        toggle() {
            this.isDone = !this.isDone;
        }
    }
});

原來定義在 App 中的 toggle() 方法也稍作改動(dòng),定義在組件內(nèi)了。toggle() 調(diào)用的時(shí)候會(huì)修改表示是否完成的 done 的值。但由于 done 是定義在 props 中的屬性,不能直接賦值,所以采用了官方推薦的第一種方法,定義一個(gè)數(shù)據(jù) isDone,初始化為 this.done,并在組件內(nèi)使用 isDone 來控制是否完成這一狀態(tài)。

相應(yīng)的 App 部分的模板和代碼精減了不少:

Todos:

new Vue({
    el: "#app",
    data: {
        todos: [
            { text: "Learn JavaScript", done: false },
            { text: "Learn Vue", done: false },
            { text: "Play around in JSFiddle", done: true },
            { text: "Build something awesome", done: true }
        ]
    }
});

JsFiddle 演示

https://jsfiddle.net/0okxhc6f/1/

不過到此為止,數(shù)據(jù)仍然是單向的。從效果上來看,點(diǎn)擊復(fù)選框可以反饋出刪除線線效果,但這些動(dòng)態(tài)變化都是在 todo 組件內(nèi)部完成的,不存在數(shù)據(jù)綁定的問題。

為 Todo List 添加計(jì)數(shù)

為了讓 todo 組件內(nèi)部的狀態(tài)變化能在 Todo List 中呈現(xiàn)出來,我們?cè)?Todo List 中添加計(jì)數(shù),展示已經(jīng)完成的 Todo 數(shù)量。因?yàn)檫@個(gè)數(shù)量受 todo 組件內(nèi)部狀態(tài)(數(shù)據(jù))的影響,這就需要將 todo 內(nèi)部數(shù)據(jù)變化反應(yīng)到其父組件中,這才有 v-model 的用武之地。

這個(gè)數(shù)量我們?cè)跇?biāo)題中以 n/m 的形式呈現(xiàn),比如 2/4 表示一共 4 條 Todo,已經(jīng)完成 2 條。這需要對(duì) Todo List 的模板和代碼部分進(jìn)行修改,添加 countDonecount 兩個(gè)計(jì)算屬性:

Todos ({{ countDone }}/{{ count }}):

new Vue({
    // ...
    computed: {
        count() {
            return this.todos.length;
        },
        countDone() {
            return this.todos.filter(todo => todo.done).length;
        }
    }
});

現(xiàn)在計(jì)數(shù)呈現(xiàn)出來了,但是現(xiàn)在改變?nèi)蝿?wù)狀態(tài)并不會(huì)對(duì)這個(gè)計(jì)數(shù)產(chǎn)生影響。我們要讓子組件的變動(dòng)對(duì)父組件的數(shù)據(jù)產(chǎn)生影響。v-model 待會(huì)兒再說,先用最常見的方法,事件:

  • 子組件 todotoggle() 中觸發(fā) toggle 事件并將 isDone 作為事件參數(shù)
  • 父組件為子組件的 toggle 事件定義事件處理函數(shù)
Vue.component("todo", {
    //...
    methods: {
        toggle(e) {
            this.isDone = !this.isDone;
            this.$emit("toggle", this.isDone);
        }
    }
});

這里為 @toggle 綁定的是一個(gè)表達(dá)式。因?yàn)檫@里的 todo 是一個(gè)臨時(shí)變量,如果在 methods 中定義專門的事件處理函數(shù)很難將這個(gè)臨時(shí)變量綁定過去(當(dāng)然定義普通方法通過調(diào)用的形式是可以實(shí)現(xiàn)的)。

事件處理函數(shù),一般直接對(duì)應(yīng)于要處理的事情,比如定義 onToggle(e),綁定為 @toggle="onToggle"。這種情況下不能傳入 todo 作為參數(shù)。

普通方法,可以定義成 toggle(todo, e),在事件定義中以函數(shù)調(diào)用表達(dá)式的形式調(diào)用:@toggle="toggle(todo, $event)"。它和todo.done = $event` 同屬表達(dá)式。

注意二者的區(qū)別,前者是綁定的處理函數(shù)(引用),后者是綁定的表達(dá)式(調(diào)用)

現(xiàn)在通過事件方式已經(jīng)達(dá)到了預(yù)期效果

Js Fiddle 演示

https://jsfiddle.net/0okxhc6f/2/

改造成 v-model

之前我們說了要用 v-model 實(shí)現(xiàn)的,現(xiàn)在來改造一下。注意實(shí)現(xiàn) v-model 的幾個(gè)要素

  • 子組件通過 value 屬性(Prop)接受輸入
  • 子組件通過觸發(fā) input 事件輸出,帶數(shù)組參數(shù)
  • 父組件中用 v-model 綁定
Vue.component("todo", {
    // ...
    props: ["text", "value"],   // <-- 注意 done 改成了 value
    data() {
        return {
            isDone: this.value    // <-- 注意 this.done 改成了 this.value
        };
    },
    methods: {
        toggle(e) {
            this.isDone = !this.isDone;
            this.$emit("input", this.isDone);  // <-- 注意事件名稱變了
        }
    }
});

.sync 實(shí)現(xiàn)其它數(shù)據(jù)綁定

前面講到了 Vue 2.2.0 引入 v-model 特性。由于某些原因,它的輸入屬性是 value,但輸出事件叫 inputv-model、value、input 這三個(gè)名稱從字面上看不到半點(diǎn)關(guān)系。雖然這看起來有點(diǎn)奇葩,但這不是重點(diǎn),重點(diǎn)是一個(gè)控件只能雙向綁定一個(gè)屬性嗎?

Vue 2.3.0 引入了 .sync 修飾語(yǔ)用于修飾 v-bind(即 :),使之成為雙向綁定。這同樣是語(yǔ)法糖,添加了 .sync 修飾的數(shù)據(jù)綁定會(huì)像 v-model 一樣自動(dòng)注冊(cè)事件處理函數(shù)來對(duì)被綁定的數(shù)據(jù)進(jìn)行賦值。這種方式同樣要求子組件觸發(fā)特定的事件。不過這個(gè)事件的名稱好歹和綁定屬性名有點(diǎn)關(guān)系,是在綁定屬性名前添加 update: 前綴。

比如 <sub :some.sync="any" /> 將子組件的 some 屬性與父組件的 any 數(shù)據(jù)綁定起來,子組件中需要通過 $emit("update:some", value) 來觸發(fā)變更。

上面的示例中,使用 v-model 綁定始終感覺有點(diǎn)別扭,因?yàn)?v-model 的字面意義是雙向綁定一個(gè)數(shù)值,而表示是否未完成的 done 其實(shí)是一個(gè)狀態(tài),而不是一個(gè)數(shù)值。所以我們?cè)俅螌?duì)其進(jìn)行修改,仍然使用 done 這個(gè)屬性名稱(而不是 value),通過 .sync 來實(shí)現(xiàn)雙向綁定。

Vue.component("todo", {
    // ...
    props: ["text", "done"],   // <-- 恢復(fù)成 done
    data() {
        return {
            isDone: this.done    // <-- 恢復(fù)成 done
        };
    },
    methods: {
        toggle(e) {
            this.isDone = !this.isDone;
            this.$emit("update:done", this.isDone);  // <-- 事件名稱:update:done
        }
    }
});


Js Fiddle 演示

https://jsfiddle.net/0okxhc6f/3/

揭密 Vue 雙向綁定

通過上面的講述,我想大家應(yīng)該已經(jīng)明白了 Vue 的雙向綁定其實(shí)就是普通單向綁定和事件組合來完成的,只不過通過 v-model.sync 注冊(cè)了默認(rèn)的處理函數(shù)來更新數(shù)據(jù)。Vue 源碼中有這么一段

// @file: src/compiler/parser/index.js

if (modifiers.sync) {
    addHandler(
        el,
        `update:${camelize(name)}`,
        genAssignmentCode(value, `$event`)
    )
}

從這段代碼可以看出來,.sync 雙向綁定的時(shí)候,編譯器會(huì)添加一個(gè) update:${camelize(name)} 的事件處理函數(shù)來對(duì)數(shù)據(jù)進(jìn)行賦值(genAssignmentCode 的字面意思是生成賦值的代碼)。

展望

目前 Vue 的雙向綁定還需要通過觸發(fā)事件來實(shí)現(xiàn)數(shù)據(jù)回傳。這和很多所的期望的賦值回傳還是有一定的差距。造成這一差距的主要原因有兩個(gè)

  1. 需要通過事件回傳數(shù)據(jù)
  2. 屬性(prop)不可賦值

在現(xiàn)在的 Vue 版本中,可以通過定義計(jì)算屬性來實(shí)現(xiàn)簡(jiǎn)化,比如

computed: {
    isDone: {
        get() {
            return this.done;
        },
        set(value) {
            this.$emit("update:done", value);
        }
    }
}

說實(shí)在的,要多定義一個(gè)意義相同名稱不同的變量名也是挺費(fèi)腦筋的。希望 Vue 在將來的版本中可以通過一定的技術(shù)手段減化這一過程,比如為屬性(Prop)聲明添加 sync 選項(xiàng),只要聲明 sync: true 的都可以直接賦值并自動(dòng)觸發(fā) update:xxx 事件。

當(dāng)然作為一個(gè)框架,在解決一個(gè)問題的時(shí)候,還要考慮對(duì)其它特性的影響,以及框架的擴(kuò)展性等問題,所以最終雙向綁定會(huì)演進(jìn)成什么樣子,我們對(duì) Vue 3.0 拭目以待。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。


文章標(biāo)題:揭密Vue的雙向綁定-創(chuàng)新互聯(lián)
當(dāng)前URL:http://weahome.cn/article/deeeji.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部