Vue還有這種操作?淺析幾個新手常常忽略的API


一:實現子組件與父組件雙向綁定的“sync”:

一般來說,我們實現父子組件值的傳遞通常使用的是【props】和自定義事件【$emit】。父組件通過【props】將值傳給子組件,子組件通過【$emit】將值傳給父組件,父組件通過【$on】獲取子組件傳過來的值,如果說想要實現子組件修改父組件傳過來的值,最容易的就是這種方法了:

//父組件向子組件傳值
<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】獲取子組件的值:

<template>
    <div>
        <child-com :value="text" @getChildValue = "getValue"></child-com>
    </div>
</template>

<script>
    export default{
        data(){
            return {
                text:"父組件的值",
            }
        },
        methods:{
            getValue(child_value){
                this.text = child_value;
            }
        }
    }
</script>

這樣,就可以實現子組件修改父組件的值。

不過,這種方法有一個弊端——子組件修改父組件的值需要一個傳遞的過程,或者說,兩個值並不是同步的

熟悉Vue1.0的朋友應該知道一個叫【.sync】的修飾符,它可以實現父子組件的雙向綁定,不過在Vue2.0被移除了,直到2.3.0版本發布后才重新回歸,所以一些和我一樣從2.0開始使用Vue的朋友很有可能不清楚,事實上,【.sync】可以很輕松的實現子組件同步修改父組件的值:

//父組件
<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:data',"子組件的值")
            }
        }
    }
</script>

我們可以看到,對於子組件來說,僅僅是自定義事件名做了一點改變,但是就代碼底層邏輯來說,子組件和父組件真正實現了同步的雙向綁定

當然,正如文檔所說:

.sync修飾符很方便,但也會導致問題,因為破壞了單向數據流。由於子組件改變 prop 的代碼和普通的狀態改動代碼毫無區別,當光看子組件的代碼時,你完全不知道它何時悄悄地改變了父組件的狀態。這在 debug 復雜結構的應用時會帶來很高的維護成本。

 

二:自定義指令:“directives”

關於自定義指令文檔其實介紹的比較詳細了,而且還舉了一個非常詳細的例子:自定義指令

自定義指令其實就是Vue為我們提供直接操作dom的一些列方法,雖然大部分開發時間都會面向數據,但說不准什么時候確實需要操作dom本身。

就我而言,自定義指令最大的用處就是可以引用一些第三方的代碼插入到Vue項目中,比如有一個操作dom的函數:

//當然,真實情況第三方的代碼要復雜的多
function
changeColor(dom){ dom.style.backgroundColor = "red"; }

我們可以注冊一個全局的指令來為需要執行changeColor方法的dom提供指令:

Vue.directives('color',{
    bind:function(el){
        changeColor(el)
    }
})

這樣,如果需要這個dom改變顏色的話,只需要這樣即可:

<div v-color>改變顏色</div>

 

當日常開發遇到跟dom有關的問題卻一籌莫展時,可以想想自定義指令是否有功能可以解決為題。

 

三: 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上顯示的展示了message="123456"。

此時,我們可以通過設置inheritAttrs: false來取消這種默認行為

data(){
  return{
    ......   
  }  
}

inheritAttrs: false,
mounted(){
  console.log(this.$attrs); //{count:123456}
}

這時再看dom上就沒有message屬性了。然后,我還打印了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]寫入即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM