vue自定义事件
Vue的组件通信一直都是一道常见面试题,今天面试被问一道十分简单的题目。
题目:父组件给子组件传递一个值(数据),如何做到子组件修改后,父组件也同步修改?
可能一般人,都会想到用组件的事件触发来做也就是this.$emit('事件名',参数)
然后父组件监听v-on:事件名
然后让父组件的监听处理函数来做值的修改
这样虽然可以做,但是如果我又很多个子组件,那不要重复写事件触发,然后监听的代码?很明显太累了。其实我自己也忘了还有啥方式。(文档有更新忘记了)
不过你可以使用$parent
直接操作父组件属性,不过这个非常不推荐,或者你传递一个操作父组件属性的函数,交给子组件来调用。(都不好)
正确方式其实在官网有提到:(自定义事件)cn.vuejs.org/v2/guide/co…
使用场景:www.cnblogs.com/wind-lanyan…
个人测试代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01-自定义事件</title>
<script src="../js/vue.js"></script>
</head>
<div id="app">
<base-checkbox v-model="lovingVue"></base-checkbox>
<div>lovingVue:{{lovingVue}}</div>
</div>
<body>
</body>
<script>
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
var app = new Vue({
el: '#app',
data() {
return {
lovingVue: false
}
},
})
</script>
</html>
.sync
修饰符
深入理解vue 修饰符sync:www.jianshu.com/p/6b062af8c…
2.3.0+ 新增
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。
这也是为什么我们推荐以 update:myPropName
的模式触发事件取而代之。举个例子,在一个包含 title
prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:
this.$emit('update:title', newTitle)
然后父组件可以监听那个事件并根据需要更新一个本地的数据 property。例如:
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
为了方便起见,我们为这种模式提供一个缩写,即 .sync
修饰符:
<text-document v-bind:title.sync="doc.title"></text-document>
原来写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>02-sync修饰符</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
父组件
<hr>
<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event"></text-document>
{{doc.title}}
</div>
<template id="aaa">
<button @click="click">我是子组件</button>
</template>
</body>
<script>
Vue.component('text-document', {
template: '#aaa',
methods: {
click() {
this.$emit('update:title', '新标题')
}
},
})
var app = new Vue({
el: '#app',
data() {
return {
doc: {
title: '你好'
}
}
},
})
</script>
</html>
使用sync简化后
就是把指令做了简化
`<text-document v-bind:title.sync="doc.title"></text-document>`
这帮我做了什么?
答案:很明显,这样帮助我们,好多时候子组件需要主动修改父组件的值,或者绑定。
这时候再用单纯的父子组件通信显得不合适,最好是让父组件不在过多的自己去操作数据,不然就不像一个本分的组件了,这时候就需要v-model(自定义组件的v-model)。
vue 修饰符sync的功能是:当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。如果我们不用.sync,我们想做上面的那个弹窗功能,我们也可以props传初始值,然后事件监听,实现起来也不算复杂。
完整样例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>02-sync修饰符</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
父组件
<hr>
<!-- <text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event"></text-document> -->
<!-- 简化后 -->
<text-document v-bind:title.sync="doc.title"></text-document>
{{doc.title}}
{{doc}}
</div>
<template id="aaa">
<button @click="click">我是子组件</button>
<!-- <button>我是子组件</button> -->
</template>
</body>
<script>
Vue.component('text-document', {
template: '#aaa',
methods: {
click() {
this.$emit('update:title', '新标题')
}
},
})
var app = new Vue({
el: '#app',
data() {
return {
doc: {
title: '你好'
}
}
},
})
</script>
</html>
这篇写的针对上述问题做了组件通信的分类与区别,这就是上面那道题目最棒的解答了:www.cnblogs.com/penghuwan/p…
v-model实现下拉框原理
在Vue中 使用select下拉框 主要靠的是 v-model 来绑定选项 option 的 value 值。
常见使用方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>03-v-model绑定下拉列表</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<select name="status" id="status" v-model="selected">
<!-- <option value="">请选择</option>
<option value="1">未处理</option>
<option value="2">处理中</option>
<option value="3">处理完成</option> -->
<option :value="item.statusId" v-for="(item,index) in statusArr">{{item.statusVal}}</option>
</select>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data() {
return {
//默认选中项的value值是什么 就给绑定的属性什么值 这里默认选中项请选择的value值是空 我们就给绑定的属性 select 一个空值
selected: '',
statusArr: [
{
statusId: '0',
statusVal: '请选择'
},
{
statusId: '1',
statusVal: '未处理'
},
{
statusId: '2',
statusVal: '处理中'
},
{
statusId: '3',
statusVal: '处理完成'
},
],
}
},
created() {
// 在组件创建之后,把默认选中项的value值赋给绑定的属性
//如果没有这句代码,select中初始化会是空白的,默认选中就无法实现
this.selected = this.statusArr[0].statusId
},
})
</script>
</html>