目录
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、效果图