一、视频教程
- sync修饰符原理详解
- sync修饰符原理和v-model一样可以对比理解:Vue框架,v-model 原理详解和代码demo、视频教程
二、原理和作用
原理
- sync修饰符本质就是语法糖::属性名和@update:属性名
:isShow.sync="isShow" 等价于 :isShow="isShow" @update:isShow="isShow=$event"
- prop属性名,可以自定义,非固定为value
- 当属性名确定的时候,子组件的事件同时确定。比如当属性名为 isShow,子组件的事件必须为 update:isShow,否则 sync 会失效。
作用
- 封装弹框类的基础组件,visible属性 true显示false隐藏
- 可以实现子组件与父组件数据的双向绑定,简化代码。
三、自定义组件实现sync修饰符
-
当自定义组件实现sync修饰符时,子组件 props 接收的变量名没有限制,但是该变量名与事件名需要一一对应,否则sync修饰符将失效,比如当变量名为show时,事件名必须为 update:show。
-
可自行更改代码,即可理解
-
优点:父组件v-model 简化代码,实现子组件和父组件数据双向绑定。父组件简化了代码,子组件的代码并没有简化
-
页面显示效果
单文件demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Prop</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<!--
-->
<body>
<div id="app">
当前isShow的值为:{{isShow}}<br>
<button @click="openDialog">退出按钮</button>
<base-dialog :show.sync="isShow"></base-dialog>
</div>
<script>
Vue.component('BaseDialog', {
template: "<div class=\"base-dialog-wrap\" v-show=\"show\">\n <div class=\"base-dialog\">\n <div class=\"title\">\n <h3>温馨提示:</h3>\n <button class=\"close\" @click=\"closeDialog\">x</button>\n </div>\n <div class=\"content\">\n <p>你确认要退出本系统么?</p>\n </div>\n <div class=\"footer\">\n <button @click=\"closeDialog\">确认</button>\n <button >取消</button>\n </div>\n </div>\n </div>",
methods:{
closeDialog(){
this.$emit('update:show',false)
}
},
props: {
show: Boolean,
}
})
let vm = new Vue({
el: "#app",
data() {
return {
isShow: false,
}
},
methods: {
openDialog() {
this.isShow = true
},
}
})
</script>
</body>
<style scoped>
.base-dialog-wrap {
width: 300px;
height: 200px;
box-shadow: 2px 2px 2px 2px #ccc;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 0 10px;
}
.base-dialog .title {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #000;
}
.base-dialog .content {
margin-top: 38px;
}
.base-dialog .title .close {
width: 20px;
height: 20px;
cursor: pointer;
line-height: 10px;
}
.footer {
display: flex;
justify-content: flex-end;
margin-top: 26px;
}
.footer button {
width: 80px;
height: 40px;
}
.footer button:nth-child(1) {
margin-right: 10px;
cursor: pointer;
}
</style>
</html>
组件版demo(两个文件)
- App.vue
<template>
<div class="app">
当前isShow的值为:{{isShow}}<br>
<button @click="openDialog">退出按钮</button>
<BaseDialog :isShow.sync="isShow"></BaseDialog>
</div>
</template>
<script>
import BaseDialog from './components/BaseDialog.vue'
export default {
data() {
return {
isShow: false,
}
},
methods: {
openDialog() {
this.isShow = true
},
},
components: {
BaseDialog,
},
}
</script>
<style>
</style>
- BaseDialog.vue
<template>
<div class="base-dialog-wrap" v-show="isShow">
<div class="base-dialog">
<div class="title">
<h3>温馨提示:</h3>
<button class="close" @click="closeDialog">x</button>
</div>
<div class="content">
<p>你确认要退出本系统么?</p>
</div>
<div class="footer">
<button @click="closeDialog">确认</button>
<button >取消</button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
isShow: Boolean,
},
methods:{
closeDialog(){
this.$emit('update:isShow',false)
}
}
}
</script>
<style scoped>
.base-dialog-wrap {
width: 300px;
height: 200px;
box-shadow: 2px 2px 2px 2px #ccc;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 0 10px;
}
.base-dialog .title {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #000;
}
.base-dialog .content {
margin-top: 38px;
}
.base-dialog .title .close {
width: 20px;
height: 20px;
cursor: pointer;
line-height: 10px;
}
.footer {
display: flex;
justify-content: flex-end;
margin-top: 26px;
}
.footer button {
width: 80px;
height: 40px;
}
.footer button:nth-child(1) {
margin-right: 10px;
cursor: pointer;
}
</style>