目錄
1.1在上面的基礎例子上的methods裏面添加commit方法:
-
參考文章
-
需求
當子頁面數據發生變化的時候,父頁面的結果也需要更新,由於數據是單向傳遞,是不可以直接需改父頁面的數據,那麼我們該怎麼操作呢?本篇文章可以利用2種方式(sync、v-model)實現效果都是一樣的,區別在於一個要在父頁面聲明傳遞的數據對象,一個是在子頁面去解析傳遞的對象是給什麼data裏面的屬性。
我們從官網element-ui中拿一個select下拉框來做實驗:
1、第一步、全局子組件定義child
Vue.component("child", {
data: function () {
return {}
},
template: ``,
methods:{}
});
2、第二步、放官網select例子
Vue.component("child", {
data: function () {
return {
options: [{
value: '選項1',
label: '黃金糕'
}, {
value: '選項2',
label: '雙皮奶'
}, {
value: '選項3',
label: '蚵仔煎'
}, {
value: '選項4',
label: '龍鬚麪'
}, {
value: '選項5',
label: '北京烤鴨'
}],
value: ''
}
},
template: `
<div>
<el-select v-model="value" placeholder="請選擇">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
`,
methods: {
}
});
3、第三步、普通的父子交互方法
1.1在上面的基礎例子上的methods裏面添加commit方法:
methods: {
commit() {
this.$emit('output', this.value);
},
}
1.2在父頁面中利用方法去獲取子頁面內容:
<p style="font-size: 13px">父組件2:{{foo}}</p>
<child :give="foo" @output="output"></child>
......
let vue = new Vue({ el: '#app', data: { foo: null, }, methods: { output(data){ this.foo = data; console.log('通過方法獲取子對象屬性變化:', foo); },
......
1.3實際效果gif
4、第四步、sync的watch方法
這裏give是外部需要傳入的數據,this.value是子頁面不斷修改的數據。
如果當你寫完這個,你的html頁面就可以利用下面➷➷➷➷➷➷實現數據交互。從這個我們可以知道當使用sync的時候要在父頁面明確聲明你傳值給誰。
<child :give.sync="foo"></child>
props: ['give'],
watch: {
'give': function (newVal, oldVal) {
this.value = newVal;
},
value: function (newVal, oldVal) {
this.$emit("update:give", newVal);
}
},
5、第五步、v-model的雙向綁定
1.1、聲明傳過來的值付賦給什麼屬性
解釋例子傳參,
model: { prop: '父接收屬性', event: 'commit(普通方法定義接收值)' },
如在上面所說的最普通實現父子交互是:
<child :give="foo" @output="output"></child>
從這個我們可以將參數補充進去:
model: { prop: 'give',// 即:give event: 'output'// 即@output },
1.2、this.$emit
如果你在使用v-model中沒有添加commit方法是需要添加的
methods: {
commit() {
this.$emit('output', this.value);
},
}
1.3、子頁面增加v-model和event綁定
......
<el-select v-model="value" placeholder="請選擇" @change="commit">
......
上面3個效果都是等同的,看你想要用什麼去實現了。
-
總結
1、普通方法
使用簡單,但是需要在父頁面中定義接收方法,需要子methods裏面使用emit,如果說自定義組件比較多,父頁面的方法就會很臃腫;
<child :give="foo" @output="output"></child>
2、sync
使用簡單,但是需要在父頁面中定義具體傳參值,在watch中使用emit,如果自定義組件比較多,每個頁面傳值定義的單詞又不一樣,容易暈眩;
<child :give.sync="foo"></child>
3、v-model
使用簡單,父頁面幾乎不需要幹什麼,將具體綁定都什麼對象由子頁面去分析,需要定義model,在methods裏面使用emit,也比較簡潔。
<child v-model="foo"></child>
-
全局代碼
-
1、child.js
Vue.component("child", {
data: function () {
return {
options: [{
value: '選項1',
label: '黃金糕'
}, {
value: '選項2',
label: '雙皮奶'
}, {
value: '選項3',
label: '蚵仔煎'
}, {
value: '選項4',
label: '龍鬚麪'
}, {
value: '選項5',
label: '北京烤鴨'
}],
value: ''
}
},
props: ['give'],
watch: {
'give': function (newVal, oldVal) {
this.value = newVal;
},
value: function (newVal, oldVal) {
this.$emit("update:give", newVal);
}
},
model: {
prop: 'give',
event: 'commit'
},
template: `
<div>
<el-select v-model="value" placeholder="請選擇" @change="commit">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
`,
methods: {
commit() {
this.$emit('output', this.value);
},
}
});
-
2、demo.html
<script th:src="@{~/js/components/jt/child.js}"></script>
<child :give="foo" @output="output"></child> <child :give.sync="foo"></child> <child v-model="foo"></child>
<script type="text/javascript"> let vue = new Vue({ el: '#app', data: { foo: null, }, methods: { output(data){ this.foo = data; console.log('通過方法獲取子對象屬性變化:', this.foo) }, } }) </script>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head th:replace="common/header :: header">
</head>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" th:href="@{~/css/ui/reset.css}">
<link rel="stylesheet" th:href="@{~/css/ui/index.css}">
<script th:src="@{~/js/components/jt/child.js}"></script>
</head>
<body>
<div id="app">
<p style="font-size: 13px">父組件2:{{foo}}</p>
普通方法:<child :give="foo" @output="output"></child>
sync:<child :give.sync="foo"></child>
v-model:<child v-model="foo"></child>
</div>
</body>
<script type="text/javascript">
let vue = new Vue({
el: '#app',
data: {
foo: null,
},
methods: {
output(data){
this.foo = data;
console.log('通過方法獲取子對象屬性變化:', this.foo);
},
}
})
</script>
</html>
-
3、效果圖