vue $attrs 父組件和孫子組件的傳值,傳函數


上一篇我們說到provide/inject的依賴注入的傳值方法,今天我們來說一下另一個父組件給孫子組件的傳值方式$attrs

我們接着上一個例子繼續來寫

parent父組件

我們給child子組件穿了四個屬性值(title,name,hobby,age

<template>
    <div>
        <button @click="add" >點擊增加年齡</button>
        <child :title="title" :name='name' :hobby='hobby' :age='age'/>
    </div>
</template>
<script>
import child from '@/components/child'
export default {
    components:{child},
    data () {
        return {
            title:'自我介紹',
            name:'Tom',
            hobby:'like eat',
            age:4,
        }
    },
    methods:{
        add(){
            this.age ++

        },
    }
}
</script>

child子組件

child子組件使用props來接受,在child組件中引入childChild子組件,並使用v-bind將$attrs綁定在組件上就可在childChild組件中使用props或$attrs接收,按此規律可一直傳遞。

$attrs打印出來是一個對象,所以我們可以在子組件直接取你想要的數據值{{$attrs.name}}

當然當你的props不是空數組的話,也可以直接用{{name}}

 

<template>
<section>
    <div>我是子組件:{{$attrs}}</div>
    <childChild v-bind="$attrs"/>
</section>
</template>
<script>
import childChild from '@/components/childChild'
export default {
    props:[],
    // props:['name','age'],
    //props:['title','name','hobby','age'],
    components:{
        childChild
    },
    
}
</script>

看上面👆child組件中,我們注釋的幾個props,props他主要分三個情況,我們可以打印出來看一下

    1.  當child組件的props為[]時,$attrs會打印出所有的對象值

    child組件中:props:[],

             

    2. 當child組件的props為['name','age']時,$attrs會打印出除props里面屬性值得對象

    child組件中:props:['name','age'],

    

    3.  當child組件的props為['title','name','hobby','age']時,當把所有的父組件傳來的值都寫到props的時候,$attrs會打印出空對象

    child組件中:props:['title','name','hobby','age'],

 

  

childChild組件

<template>
    <div>
         <div>我是子組件的組件:{{$attrs}}</div>
         <div>主題:{{$attrs.title}}</div>
         <div>姓名:{{$attrs.name}}</div>
         <div>愛好:{{$attrs.hobby}}</div>
         <div>年齡:{{$attrs.age}}</div>
         
    </div>
</template>

 

當然點擊parent父組件的add按鈕的時候(增加年齡),孫子組件也是會響應的

那當我們想現在在孫子組件里改變父組件的值,怎么辦?$listeners給我們提供了一個思路,

我們只需要現在子組件引入的組件上綁定一個

<childChild v-bind="$attrs" v-on="$listeners"/>

在孫子組件用就$emit方法,這個不多說,相信很多小伙伴都懂了

<template>
    <div>
         <div>我是子組件的組件:{{$attrs}}</div>
         <div>主題:{{$attrs.title}}</div>
         <div>姓名:{{$attrs.name}}</div>
         <div>愛好:{{$attrs.hobby}}</div>
         <div>年齡:{{$attrs.age}}</div>
          <button @click="childChildChangeName" >改名字</button>
    </div>
</template>
<script>
export default {
    inject:['newFoo'],
    methods:{
        childChildChangeName(){
            this.$emit('changeName','Lili')
        }
    }
}
</script>

父組件就可以直接修改值了

<template>
    <div>
        <button @click="add" >點擊增加年齡</button>
        <child :title="title" :name='name' :hobby='hobby' :age='age' @changeName='changeName'/>
    </div>
</template>
<script>
import child from '@/components/child'
export default {
    components:{child},
    data () {
        return {
            title:'自我介紹',
            name:'Tom',
            hobby:'like eat',
            age:4,
        }
    },
    methods:{
        add(){
            this.age ++
        },
        changeName(val){
            this.name = val
        }
    }
}
</script>

 

 

$attrs可以傳函數嗎?

經過測試發現$attrs不僅可以傳對應參數,也可以傳函數,我們下面以之前的例子說明一下

還是之前的parent父組件, 我們給child組件上傳了一個changeName函數,因為組件太多我們暫時就已一代二代來區分子組件

parent父組件

<template>
    <div>
        <button @click="add" >點擊增加年齡</button>
        <child :title="title" :name='name' :hobby='hobby' :age='age' :changeName='changeName' @changeTitle='changeTitle'/>
    </div>
</template>
<script>
import child from '@/components/child'
export default {
    components:{child},
    data () {
        return {
            title:'自我介紹',
            name:'Tom',
            hobby:'like eat',
            age:4,
        }
    },
    methods:{
        add(){
            this.age ++
        },
   changeName(val){
            this.name = val
        },
   changeTitle(val){
     this.title = val
     this.name ='張三'    } } }
</script>
第一代組件

下面是我們的child第一代子組件,同時我們也相繼的給第二代組件childChild上在傳一個函數,后面繼續試一下子組件相互修改值

<button @click="$attrs.changeName(data)">一代組件修改父組件值</button>
我們打印出$attrs看一下

<template>
<section>
    <div>我是一代子組件:{{$attrs.title}}</div>
    <div>一代活動名稱:{{activity.name}}</div>
    <div>一代活動地點:{{activity.place}}</div>
    <childChild v-bind="$attrs" v-on="$listeners" :changePlace='val => activity.place = val'  />
    <button @click="$attrs.changeName(data)">一代組件修改父組件值</button>
</section>
</template>
<script>
export default {
    data () {
        return {
            data:'小明',
            activity:{
                name:'活動名稱',
                date:'活動時間',
                place:'學校'
            },
        }
    },
    props:[],
    // props:['name','age'],
    // props:['title','name','hobby','age'],
    components:{childChild},
    created(){
         console.log(this.$attrs)
    },
    
}
</script>

我們可以看到我們直接在第一點組件中調用$attrs.changeName(),並在里面傳了一個定義的data值,修改name為data的‘小明’,點擊按鈕確實是可以觸發,並修改name值,name值作為$attrs傳的值,也會一起響應觸發修改所有

我們可以看一下頁面,name值被修改成功,同時,所有的$attrs值都被重新掛載修改

所以我們也可以不通過$emit來修改父組件的值,可以把函數作為三參數傳給$attrs

第二代組件

我們上面給第二代子組件上也傳了一個函數,我們這次試一下第三代組件修改第二代組件得值,我們看一下打印出來的數據

我們傳的changePlace(),也打印出來了

我們在第二代組件里面又傳了一個第三代組件,同時我們也給第三代組件穿了一個函數

childChildChangeName()是我們第三代組件將要執行的的反方法
<template>
    <div>
         <div>我是子組件的組件:{{$attrs}}</div>
         <div>主題:{{$attrs.title}}</div>
         <div>姓名:{{$attrs.name}}</div>
         <div>愛好:{{$attrs.hobby}}</div>
         <div>年齡:{{$attrs.age}}</div>
         <div>二代組件值:{{twoData}}</div>
        <threeChild v-bind="$attrs"  :changeTwoName='childChildChangeName'></threeChild>
    </div>
</template>
<script>
import threeChild from '@/components/threeChild'
export default {
    components:{threeChild},
    data () {
        return {
            twoData:'西游記'
        }
    },
    methods:{
        childChildChangeName(){
            this.$emit('changeTitle','重新自我介紹')
            this.twoData = '水滸傳'
            this.$attrs.title = '安居客'//發現沒有修改
        }
    }
}
</script>
第三代組件

這是我們第三代組件

我們可以回頭看看第一代組件的頁面

<childChild v-bind="$attrs" v-on="$listeners" :changePlace='val => activity.place = val'  />
 
        
<template>
    <section>
        <div>我是第三代組件:{{$attrs}}</div>
        <button @click="changeOne">三修改一代組件</button>
        <button @click="changeTwo">三修改二代組件</button>
    </section>
</template>
<script>
export default {
    methods:{
        changeOne(){
            this.$attrs.name='數據庫打開'//發現不可以
            this.$attrs.changePlace('西校區')
        },
        changeTwo(){
            this.$attrs.changeTwoName()
        }    
    },
    mounted(){
    },
    created(){
         console.log('three',this.$attrs)
    },
}
</script>
我們點擊按鈕 one ,發現直接修改$attrs的屬性值是不奏效的,在調取他的changePlace(),並傳入修改的值
我們看一下修改后的頁面,點擊按鈕確實觸發了,

 
        

我們接着點擊two按鈕試一下,他調取的是第二組件的方法,第二組建的方法同時又用$emit,去觸發了父組件的一個方法,同時也試着修改了該組件的$attrs值

我們可以看上面第二代組件的代碼回顧一下

<threeChild v-bind="$attrs"  :changeTwoName='childChildChangeName'></threeChild>
具體方法是
childChildChangeName(){
            this.$emit('changeTitle','重新自我介紹')
            this.twoData = '水滸傳'
            this.$attrs.title = '安居客'//發現沒有修改
        }
修改的頁面如下,我們發現除了直接修改$attrs的值不行,其他都可以,這說明要想修改$attrs的值,只能在傳值的父組件中修改,其他的都不可以

 

 
       


免責聲明!

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



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