vue 修饰符sync
初学vue,学习到修饰符sync,说这个很重要,遂花一天时间搞懂它,安排!
在vue 1.x 中的 .sync 修饰符所提供的功能。当一个子组件改变了一个带 .sync 的prop的值时,这个变化也会同步到父组件中所绑定的值。
这很方便,但也会导致问题,因为它破坏了单向数据流。(数据自上而下流,事件自下而上走)
由于子组件改变 prop 的代码和普通的状体改动代码毫无区别,所以当你光看子组件的代码时,你完全不知道它合适悄悄地改变了父组件的状态。
这在 debug 复杂结构的应用时会带来很高的维护成本。于是在 vue 2.0 中移除了 .sync 。
但是在实际应用中,我们发现 .sync 还是有其适用之处的,比如在开发可复用的组件库时。(懵逼○△○)
我们需要做的只是 让子组件改变父组件状态的代码更容易被区分。
于是从 vue 2.3.0 开始,我们重新引入了 .sync 修饰符,但是这次它只是作为一个编译时的语法糖存在。他会被自动扩展为一个 自动更新父组件属性的 v-on 监听器。
以上是从别处知道的,sync修饰符在2.0版本中被移除过,在2.30版本又重新引入,我现在用的是2.6(vue3.0已经出来了😏,越来越香了)
官方文档 对初学者总是不太友好,太抽象了,而且知识都有一些关联,对vue不了解的同学还真看不懂,
接下来步入正题:
上代码:
//父组件
<template>
<div id="app">
<div><span>{{showMsg}}</span></div>
<button @click="toggleShow">toggle</button>
<Child @update:offShow="upShow" :msg="showMsg" v-if="show"></Child>//关键代码
</div>
</template>
<script>
import Child from './components/child.vue'
export default {
name: 'App',
components: {
Child
},
data(){
return{
show:false,
}
},
computed:{
showMsg(){
return this.show ? '禁止套娃!!' : '套娃!';
}
},
methods:{
toggleShow(){
this.show = !this.show;
},
upShow(isShow){
this.show = isShow;
}
}
}
</script>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
height: 270px;
width: 500px;
padding: 10px;
margin-top: 60px;
margin-left: auto;
margin-right: auto;
border: 2px solid rosybrown;
}
</style>
<template>
<div class="child">
<p>
<span>{{msg}}</span>
</p>
<button @click="offShow">隐身</button>
</div>
</template>
<script>
export default {
props:['msg'],
methods:{
offShow(){
this.$emit('update:offShow',false)//关键代码
}
}
}
</script>
<style scoped>
.child{
margin-top: 20px;
border: 1px solid rosybrown;
background-color: #42b983;
height: 180px;
}
</style>
效果:
我们要知道的是:
组件不能修改props外部数据
this.$emit可以触发事件,并传参
$event可以获取 e m i t 的 参 数 ( 当 然 , 这 里 我 们 并 没 有 看 到 emit的参数 (当然,这里我们并没有看到 emit的参数(当然,这里我们并没有看到event)
父组件中<Child @update:offShow="upShow" :msg="showMsg" v-if="show"></Child>
的update
你可以随便改,比如改成<Child @xx:offShow="upShow" :msg="showMsg" v-if="show"></Child>
,当然,子组件中对应的也要改成this.$emit('xx:offShow',false)
接下来就是修饰符sync
了,上代码:
//父组件
<template>
<div id="app">
<div><span>{{showMsg}}</span></div>
<button @click="toggleShow">toggle</button>
<Child :offShow.sync="show" :msg="showMsg" v-if="show"></Child>//关键代码
</div>
</template>
<script>
import Child from './components/child.vue'
export default {
name: 'App',
components: {
Child
},
data(){
return{
show:false,
}
},
computed:{
showMsg(){
return this.show ? '禁止套娃!!' : '套娃!';
}
},
methods:{
toggleShow(){
this.show = !this.show;
}
}
}
</script>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
height: 270px;
width: 500px;
padding: 10px;
margin-top: 60px;
margin-left: auto;
margin-right: auto;
border: 2px solid rosybrown;
}
</style>
//子组件
<template>
<div class="child">
<p>
<span>{{msg}}</span>
</p>
<button @click="offShow">隐身</button>
</div>
</template>
<script>
export default {
props:['msg'],
methods:{
offShow(){
this.$emit('update:offShow',false)
}
}
}
</script>
<style scoped>
.child{
margin-top: 20px;
border: 1px solid rosybrown;
background-color: #42b983;
height: 180px;
}
</style>
效果跟上面是一样的,对比一下代码,父组件只有<Child :offShow.sync="show" :msg="showMsg" v-if="show"></Child>
和methods
里少了upShow
方法,子组件里代码没变,看出区别了吗?
所谓修饰符sync
是一个编译时的语法糖,甜在哪里呢?
仔细看父组件upShow
方法:
upShow(isShow){
this.show = isShow;
}
再看子组件offShow
方法:
offShow(){
this.$emit('update:offShow',false)
}
就是用this.$emit('update:offShow',false)
触发事件,然后把参数false
传值给show
,使用修饰符sync
后,我们不在需要添加upShow
方法,直接告诉$emit
,参数直接传给我们想要赋值的变量,也就是show
,使的代码更加简化,这就是语法糖,我只有一句话,好活!!!
以上只是我个人作为初学者花了一天(半玩半学)的一些见解,不足之处请指出,谢谢!