sync
修飾符通常來講,咱們實現父子組件值的傳遞一般使用的是props
和自定義事件$emit
。父組件經過props
將值傳給子組件,子組件經過$emit
將值傳給父組件,父組件經過$on
事件獲取子組件傳過來的值,若是說想要實現子組件修改父組件傳過來的值,最容易的就是這種方法了:vue
//父組件向子組件傳值
<template>
<div>
<child-com :value="text"></child-com>
</div>
</template>
<script>
export default{
data(){
return{
text:"父組件的值",
}
}
}
</script>
複製代碼
//子組件向父組件傳值
<template>
<div @click="post"></div>
</template>
<script>
export default{
methods:{
post(){
this.$emit('getChildValue',"子組件的值")
}
}
}
</script>
複製代碼
此時父組件能夠經過$on
獲取子組件的值:es6
<template>
<div>
<child-com @getChildValue = "getValue"></child-com>
</div>
</template>
<script>
export default{
methods:{
getValue(child_value){
this.text = child_value;
}
}
}
</script>
複製代碼
這樣,就能夠實現子組件修改父組件的值。不過,這種方法有一個弊端——子組件修改父組件的值須要一個傳遞的過程,或者說,兩個值並非同步的。熟悉Vue1.0的朋友應該知道一個叫.sync
的修飾符,它能夠實現父子組件的雙向綁定,不過在Vue2.0被移除了,直到2.3.0版本發佈後才從新迴歸,因此一些和我同樣從2.0開始使用Vue的朋友頗有可能不清楚,事實上,.sync
能夠很輕鬆的實現子組件同步修改父組件的值:vuex
//父組件
<template>
<div>
<child-com :value.sync="text" ></child-com>
</div>
</template>
<script>
export default{
data(){
return {
text:"父組件的值",
}
},
}
</script>
==============================================================================================================
//子組件修改父組件的值
<template>
<div @click="post"></div>
</template>
<script>
export default{
methods:{
post(){
this.$emit('update:value',"子組件的值")
}
}
}
</script>
複製代碼
咱們能夠看到,對於子組件來講,僅僅是自定義事件名作了一點改變,可是就代碼底層邏輯來講,子組件和父組件真正實現了同步的雙向綁定。瀏覽器
固然,正如文檔所說:bash
.sync修飾符很方便,但也會致使問題,由於破壞了單向數據流。因爲子組件改變 prop 的代碼和普通的狀態改動代碼毫無區別,當光看子組件的代碼時,你徹底不知道它什麼時候悄悄地改變了父組件的狀態。這在 debug 複雜結構的應用時會帶來很高的維護成本dom
directives
關於自定義指令文檔其實介紹的比較詳細了,並且還舉了一個很是詳細的例子:自定義指令自定義指令其實就是Vue爲咱們提供直接操做dom的一些列方法,雖然大部分開發時間都會面向數據,但說不許何時確實須要操做dom自己。就我而言,自定義指令最大的用處就是能夠引用一些第三方的代碼插入到Vue項目中,好比有一個操做dom的函數:ide
//固然,真實狀況第三方的代碼要複雜的多
function changeColor(dom){
dom.style.backgroundColor = "red";
}
複製代碼
//固然,真實狀況第三方的代碼要複雜的多
Vue.directives('color',{
bind:function(el){
changeColor(el)
}
})
複製代碼
這樣,若是須要這個dom改變顏色的話,只須要這樣便可:函數
<div v-color>改變顏色</div>
複製代碼
當平常開發遇到跟dom有關的問題卻束手無策時,能夠想一想自定義指令是否有功能能夠解決爲題。post
inheritAttrs
和attrs
前面我已經提到過了,父組件經過props能夠向子組件傳值,但在平常的開發中,還有一種狀況很常見,就是父組件給子組件傳值,這個值還要從子組件傳給它的子組件,因此,咱們可能會看到這樣的代碼:學習
//父組件
<div>
<child :text="text"></child>
</div>
//子組件
<div>
<my-child :text="text"></my-child>
</div>
//子組件的子組件
<div>
<div>{{text}}</div>
</div>
複製代碼
這樣作是很是麻煩並且不易於維護的,一般狀況下,咱們可使用vuex來解決。不過,不復雜的項目中若是僅僅爲這一個問題就引入vuex其實是不必的,Vue提供了【inheritAttrs】和【attrs】兩個功能來解決這樣的問題:
//父組件
<template>
<div>
<child :text="text" :count="count"></child>
</div>
</template>
<script>
export default{
data(){
return {
text:"父組件的值",
count:123456,
}
}
}
</script>
複製代碼
//子組件
<template>
<div>{{text}}</div>
</template>
<script>
export default{
props:["text"]
}
</script>
複製代碼
注意,這裏父組件的count屬性僅僅掛在子組件上,並無使用。此時咱們打開瀏覽器,能夠看到子組件的dom上顯示的展現了count="123456"。
此時,咱們能夠經過設置inheritAttrs: false來取消這種默認行爲:
data(){
return{
......
}
}
inheritAttrs: false,
mounted(){
  console.log(this.$attrs); //{count:123456}
}
複製代碼
這時再看dom
上就沒有count
屬性了。而後,我還打印了this.$attrs
的值,值爲一個包含着count
鍵值對的Object
。也就是說,父組件沒有props
的屬性值會被保存在一個名爲$attrs
中供子組件使用,然而這並無解決開頭子組件的子組件獲取值的問題。別急,咱們只須要在子組件上加個東西就能夠了:
<template>
<div class="child"> <my-child v-bind="$attrs"></my-child> </div> </template>
複製代碼
這樣,子組件的子組件也能夠獲取這個值了。
mixins
其實這個功能有些相似於es6
中的Object.assign()
方法。根據必定的規則合併兩個配置,具體的混入策略能夠看官方文檔:mixins
混入策略混入最大的用處是把一些經常使用的data
或者methods
等抽出來,好比在個人項目中有許多個模態框,而關閉模態框的代碼邏輯是如出一轍的,爲此我沒有必要在多個組件中重複把關閉模態框的邏輯寫入methods
中,只須要在外面定義一個mixins
,在須要的組件中經過:mixins: [myMin]
寫入便可。
var mixin = {
methods: {
close: function () {
this.showModal = false; //關閉模態框
},
}
}
var vm = new Vue(
mixins: [mixin],
.......
})
複製代碼
provide
/ inject
首先感謝評論區大佬們的提醒,provide/inject
方法要比`inheritAttrs/attrs更適合用來作父組件給子組件或孫組件傳值,先發一個文檔的連接:[provide/inject][1]
//父組件使用provide
<template>
<div class="parent">
<child-component></child-component>
</div>
</template>
<script>
export default {
......
provide: {
parent: "父組件的值"
},
components:{
child-component,
},
......
</script>
//此時能夠在子組件經過這種方式獲取父組件中「parent」的值:
//子組件中
export default {
mounted(){
console.log(this.parent); //"父組件的值"
},
inject: ['parent'],
}
複製代碼
須要注意的是provide
和inject
的綁定並非響應的,可是若是咱們provide的是一個對象,那麼這個對象的屬性還是可響應的。咱們能夠用如下方法一樣能夠解決上面三中的問題
//父組件使用provide
<script>
export default {
provide () {
return {
parent: this
}
},
data () {
return {
name: ''
}
}
}
</script>
//此時能夠在子組件經過這種方式獲取父組件中全部parent全部響應數據:
//此時在子組件中this.parent.name是響應式的,即父組件的name修改,子組件獲取的name也會作出響應的變化
//子組件中
export default {
mounted(){
console.log(this.parent.name); //"父組件某個屬性的值"
},
inject: ['parent'],
}
複製代碼
轉載聲明:
做者:陳杰夫
連接:https://juejin.im/post/5adc99f56fb9a07abd0d3ee7
來源:掘金
聲明:著做權歸做者全部,謝絕商業轉載。如需轉載請聯繫原做者或者按照其原文聲明進行操做。
承諾:本站除原創之外全部的轉載內容均是得到其做者受權或者聲明可轉載的。並只是將其做爲學習和交流目的,杜絕一切商業盈利行爲。如若侵權,請聯繫咱們刪除。
複製代碼
91Code-就要編碼,關注公衆號獲取更多內容!