你不知道的vue組件傳值方式

前言

上一篇關於vue面試的文章 (面試時面試官想要聽到什麼答案) 中提到了多種組件傳值方式,本文對幾種傳值方式如何使用具體說明一下。html

props、$emit、eventbus、vuex、$parent / $children / ref、sessionStorage、localStorage、路由傳參(也是傳值) 這些傳值方式都太常見了,並且每個使用vue的人都不可能不知道,因此本文就不一一說明了,如今介紹幾種平時不常見的傳值方式。若是對以上幾個有疑問的能夠在評論中留言,感謝撥冗翻閱拙做,敬請斧正。vue

1. provide/ inject

父組件中經過provide來提供變量, 而後再子組件中經過inject來注入變量。
注意: 這裏不論子組件嵌套有多深, 只要調用了inject 那麼就能夠注入provide中的數據,而不侷限於只能從當前父組件的props屬性中回去數據
假設A爲父組件B和C均爲A的子組件,D爲B的子組件,則在A組件中使用provide定義變量,在B、C、D組件中都可經過inject拿到傳過來的值。(provide中定義的變量不可在父組件中 使用)面試

注:provide 和 inject 主要爲高階插件/組件庫提供用例。並不推薦直接用於應用程序代碼中。(官方文檔描述)vuex

父組件

export default {
    data () {
        return {}
    },
    provide: {
        index: '來自index的數據'
    }
}
複製代碼

子 組件

export default {
    data () {
        return {}
    },
    inject: ['index']  // 直接能夠在頁面使用index或在js中進行賦值
}
複製代碼

2. $attrs

在父組件A中調用子組件three:<custom-three :custom="custom" :custon="custon" />,子組件three使用props進行接收,未被子組件使用props接收的能夠使用$attrs拿到傳遞的值,即three組件分爲如下狀況
bash

  1. props: ['custom','custon] 時,$attrs = {};
  2. props: ['custom'] 時,$attrs = {custon: 'ton'};
  3. props: [] 時,$attrs = {custom: 'tom', custon: 'ton'};

此時,在three組件中引入four子組件,並使用v-bind將$attrs綁定在組件上<custom-four v-bind="$attrs" />便可在four中使用props或$attrs接收,按此規律可一直傳遞。session

而且未被組件使用的變量將顯示在html結構中,例:

<div custon="ton">
    <p>three---tom</p> >
    <p>attr---{}</p>
</div>
複製代碼

在子組件中添加inheritAttrs能夠將div標籤的 custon="ton" 隱藏,inheritAttrs默認值爲true,將其設爲false便可隱藏。注意:將inheritAttrs設爲false並不會影響$attrs的使用。ide

3.$listeners

2中講述的是使用$attrs將父組件的值隔代傳給子組件,本小節中的$listeners就是將方法從父組件隔代傳給子組件,實現子組件調用時將子組件的值隔代傳給父組件。函數

首先在父組件A中調用子組件three:<custom-three @customEvent="customEvent" />,此時在子組件A中使用$listeners接收,拿到的是一個對象{customEvent: function(){...}},在three組件中再調用子組件four,並使用v-on將$listeners綁定在子組件上`` ,此時在子組件four中便可直接直接訪問customEvent或使用$listeners訪問customEvent。post

父組件A

<template>
<div>
    <custom-three :custom="custom" :custon="custon" @customEvent="customEvent"></custom-three>
</div>
</template>

<script>
import customThree from './chuanzhi/three'
export default {
    data () {
        return {
            custom: 'tom',
            custon: 'ton'
        }
    },
    components: {
        customThree
    },
    mounted () {},
    methods: {
        customEvent(data) {
            console.log('data', data)
        }
    }
}
</script>
複製代碼

子組件three

<template>
    <div>
        <p>three---{{ custom }}</p>
        <p>attr---{{$attrs}}</p>
        <p>-------------------------------------</p>
        <custom-four v-bind="$attrs" v-on="$listeners"></custom-four>
    </div>
</template>

<script>
import customFour from './four'
export default {
    data() {
        return {}
    },
    components: {
        customFour
    },
    props: ['custom'],
    inheritAttrs:false
    created() {
        console.log('1', this.$listeners)
    }
}
</script>
複製代碼

子組件four

<template>
    <div>
        <p>four---{{ custon }}</p>
        <p>attr---{{$attrs}}</p>
        <el-button @click="fashe">發射</el-button>
    </div>
</template>

<script>
export default {
    data() {
        return {}
    },
    props: ['custon'],
    inheritAttrs:false
    created() {
        console.log('2', this.$listeners)
    },
    methods: {
        fashe() {
            this.$emit('customEvent', 'piupiupiu')
        }
    }
}
</script>
複製代碼

observable實現狀態管理

observable讓一個對象可響應。Vue 內部會用它來處理 data 函數返回的對象。ui

返回的對象能夠直接用於渲染函數和計算屬性內,而且會在發生改變時觸發相應的更新。也能夠做爲最小化的跨組件狀態存儲器,用於簡單的場景:

在組件1中調用setCount使count加1或減1,各個組件內調用的count都將進行改變,並會觸發組件刷新

store.js文件

import vue from 'vue';
export const store =  vue.observable({count: 0});
export const mutation = {
  setCount( count ){
    store.count = count;
  }
}
複製代碼

組件1

<template>
  <div class="hello">
    <p @click="setCount(testCount + 1)">+</p>
    <p @click="setCount(testCount - 1)">-</p>
    <test />
    <p>{{testCount}}</p>
  </div>
</template>

<script>
import test from './test'
import { store,  mutation} from './store.js'
export default {
  name: 'HelloWorld',
  components: {
    test
  },
  methods: {
    setCount: mutation.setCount
  },
  computed: {
    testCount(){
      return store.count
    }
  }
}
複製代碼

組件2

<template>
  <div>test{{testCount}}</div>
</template>
<script>
import { store } from './store.js';
export default {
  computed: {
    testCount(){
      return store.count
    }
  }
}
</script>
複製代碼
相關文章
相關標籤/搜索