Vue 組件間傳參最佳實踐

1.父子組件間的數據傳遞

1.1從父組件獲取子組件的數據

1.1.1經過綁定 props 將父組件的數據關聯到子組件,並修飾 .sync 或者用 v-model 同步來自子組件的數據變化前端

//使用.sync :

//父組件
<template>
  <div class="home">
   <my-dialog :show.sync="valueChild"/>
   <button @click="changeValue">toggle</button>
  </div>
</template>
<script>
import myDialog from '@/components/myDialog.vue'

export default {
  name: 'home',
  components: {
    myDialog
  },
  data(){
    return{
       valueChild:true,
    }
  },
   methods:{
      changeValue(){
          this.valueChild = !this.valueChild
      }
    }
}
</script>

//子組件
<template>
  <div>
    <div>myDialog</div>
    <div v-if="show">
      <p>默認初始值是{{show}},因此是顯示的</p>
      <button @click.stop="closeDiv">關閉</button>
    </div>
  </div>
</template>
<script>
export default {
  props:['show'],
  methods:{
    closeDiv(){
      this.$emit('update:show',false)
    }
  }
}
</script>
// v-model :

//父組件:
<template>
  <div class="home">
    <myDialog v-model="show"></myDialog>
    <button @click="toggle">Toggle</button>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        show: false
      }
    },
    methods: {
      toggle() {
        this.show = !this.show
      }
    }
  }
</script>

//子組件:
<template>
  <div>
    <div v-if="value" class="modal">
      {{value}}
      <button @click="close">x</button>
    </div>
  </div>
</template>
<script>
  export default {
    props: ['value'],
    methods: {
      close() {
        this.$emit('input', false)
      }
    }
  }
</script>

1.1.2綁定 listener 事件監聽器,當子組件狀態或者數據發生變化時,觸發事件並將數據傳遞到父組件vue

$listeners 和 $attrs 二者表面層都是一個意思,$attrs 是向下傳遞數據,$listeners 是向下傳遞方法,經過手動去調用 $listeners 對象裏的方法,原理就是 $emit 監聽事件,$listeners 也能夠當作一個包裹監聽事件的一個對象。
// 父組件:
<template>
  <div class="home">
    {{firstMsg}}
    <myDialog v-on:changeData="changeData" v-on:another='another'></myDialog>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        firstMsg: '父組件'
      }
    },
    methods: {
      changeData(params) {
        this.firstMsg = params
      },
      another() {
        alert(2)
      }
    }
  }
</script>

//子組件:
<template>
  <div>
    <p @click="$emit('another')">子組件</p>
    <other v-on="$listeners"/>
  </div>
</template>
<script>
  import other from '@/components/other.vue'
  export default {
    props: ['value'],
    components:{
      other
    },
    created () {
     // eslint-disable-next-line no-console
     console.log(this.$listeners)
   }
  }
</script>

//孫子組件:
<template>
  <div>
    <p @click='$listeners.changeData("change")'>孫子組件</p>
  </div>
</template>

<script>
export default {
  name: 'demo',
  created () {
      // eslint-disable-next-line no-console
      console.log(this.$listeners)
  },
}
</script>

1.2從子組件獲取父組件的數據

1.2.1 獲取 props 或者 $attrs 傳下來的數據this

//父組件:
<template>
  <div class="home">
    <myDialog :foo="foo" :boo="boo" :coo="coo" :doo="doo" title="前端工匠"></myDialog>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        foo: "Javascript",
        boo: "Html",
        coo: "CSS",
        doo: "Vue"
      }
    },
    methods: {
      changeData(params) {
        this.firstMsg = params
      },
      another() {
        alert(2)
      }
    }
  }
</script>

//子組件:
<template>
  <div>
    <p>foo:{{foo}}</p>
    <p>子組件的$attrs: {{ $attrs }}</p>
    <other v-bind="$attrs" />
  </div>
</template>
<script>
  import other from '@/components/other.vue'
  export default {
    components: {
      other
    },
    inheritAttrs: false, // 能夠關閉自動掛載到組件根元素上的沒有在props聲明的屬性
    props: {
      foo: String // foo做爲props屬性綁定
    },
    created() {
      // eslint-disable-next-line no-console
      console.log(this.$attrs);
    }
  }
</script>

//孫子組件:
<template>
  <div>
    <p>boo: {{ boo }}</p>
    <p>孫子:{{$attrs}}</p>
  </div>
</template>

<script>
  export default {
    name: 'demo',
    inheritAttrs: false,
    props: {
      boo: String
    },
    created() {
      // eslint-disable-next-line no-console
      console.log(this.$attrs);
    },
  }
</script>

2.兄弟組件間的數據傳遞

處於兄弟關係的組件

2.1經過 EventBus 或者 $root 去註冊事件,由兄弟組件去監聽事件傳遞過來的數據變化 eslint

2.2 在 Vuex 存放狀態,並在兩個組件中都監聽狀態變化
2.3 在父組件上綁定狀態,並經過 v-model 或者 .sync 綁定到兩個兄弟組件中去,以同步數據變化code

3.祖孫組件間的數據傳遞

3.1孫組件被直接寫在了祖先組件的 template 內

在 Vue 中,處於祖孫關係的組件,並且孫組件被直接寫在了祖先組件的 template 內,要從祖先組件獲取孫組件的數據,有如下幾種方式:component

3.1.1能夠在模板上給孫組件綁定 ref 並經過 $refs 調用孫組件的方法獲取數據對象

//父組件
<template>
  <div class="home">
    {{title}}
    {{text}}
    <myDialog ref="comA"></myDialog>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        title:'',
        text:''
      }
    },
    computed: {
    },
    mounted() {
      const comA = this.$refs.comA;
      // console.log(comA.title); // Vue.js
      this.title = comA.title
      this.text = comA.text
      comA.sayHello(); // 彈窗
    },
    methods: {}
  }
</script>

//子組件:
<template>
  <div>
    <div v-if="show">sayHello</div>
    <other ref="comB" />
  </div>
</template>
<script>
  import other from '@/components/other.vue'
  export default {
    components: {
      other
    },
    data() {
      return {
        title: 'Vue.js',
        show: false,
        text:''
      }
    },
    created() {

    },
    mounted() {
      const comB = this.$refs.comB;
      this.text = comB.text
    },
    methods: {
      sayHello() {
        this.show = true
        // window.alert('Hello');
      }
    }
  }
</script>

//孫子組件:
<template>
  <div>
  </div>
</template>

<script>
  export default {
    name: 'demo',
    data(){
      return{
        text:'c'
      }
    },
    created() {
    },
  }
</script>

3.1.2 能夠在模板上給孫組件綁定 listener 獲取孫組件傳過來的數據
3.1.3 能夠在模板上給孫組件綁定 v-model 或者 .sync 同步孫組件的數據事件

3.2孫組件不在祖先組件的 template 內,要從祖先組件獲取孫組件的數據

3.2.1先在子組件上綁定 v-model 或者 .sync,接着再在子組件的模板上經過 v-model 或者 .sync 綁定孫組件,以同步孫組件的數據
3.2.2如今孫組件上綁定 listener,再給子組件綁定 listener,數據由事件層層上傳給祖先組件ip

3.3孫組件在祖先組件的 template 內,要從孫組件獲取祖先組件的數據

3.3.1直接在祖先組件的 template 中經過 v-bind 將數據傳遞到孫組件中,孫組件經過 props 或者 $attrs 進行接收input

3.4孫組件不在祖先組件的 template 內,要從孫組件獲取祖先組件的數據

3.4.1先在子組件上 v-bind 綁定數據,接着再在子組件上經過 v-bind 綁定孫組件,數據層層向下傳遞3.4.2孫組件在 EventBus 中註冊事件,監聽來自祖先組件觸發的事件數據3.4.3祖先組件將數據掛到 Vuex 中,再由孫組件從 Vuex 中去獲取數據

相關文章
相關標籤/搜索