Vue學習筆記之父子組件通信以及經典案例

父組件、子組件直接的訪問方式:

1、父組件訪問子組件可以用$childern 或者$refs

$childern 的用法:

當父組件引用多個子組件的時候,就會生成多個對應的對象:

$childern可以訪問子組件中的方法、data等數據

但$childern一般在開發中比較少用,用$refs比較常用,因爲$refs是可以通過key來絕對定位到對應的子組件,這種方法在實際開發中比較常用。$refs是一個對象類型,默認是一個空對象,在引用的時候通過ref = key 值來生成一個實例對象:

 

2、子組件訪問父組件用$parent

但是在實際開發是不會這樣使用的,因爲如果這樣嵌套組件的話,裏面的子組件就不夠獨立了,導致子組件的複用性不強,與父組件的耦合度高。

如果需要訪問跟組件裏面的方法或數據,則可以用$root進行訪問:

 

 

經典小案例:

  1. 功能需求:通過組件,有兩個數據輸入,由子組件輸入的數字,改變父組件的數字,反之亦然,並且兩個數字成倍數相互影響。

 

1、在我們實現這個需求的時候,我們第一想到的就是通過v-model進行輸入框與data數據的綁定,由於子組件只能訪問自己的數據,所以我們一開始想到的最簡單的辦法是:

但是這樣編譯器會反饋一個錯誤信息給我們:

大概的意思是:避免直接修改prop裏的值,應該要通過父組件進行值的修改。代替方案:通過修改子組件的Data函數進行值修改,或者通過計算的方法,替代方案如下:

此時不再報錯,但是我們發現當改變輸入框的值時,props裏面的值時沒有發生變化的。原因是Input輸入框裏面綁定的是data()函數中的字段。所以要改變子組件裏面的數據,需要通過data函數或計算方法進行修改,不要直接綁定props裏面的字段!但是展示是可以直接用props裏面的字段。

2、爲了實現修改props裏面數據,我們將v-modle進行拆分:v-bind、v-on進行處理:

子組件:

父組件:

3、第一個數字是第二個數字的倍數關係,而且給變任何一個值,就會影響另外一個值

爲了實現此功能,在num1Input(event)事件中進一步修改另外一個數字的值:

改變data1的值,相應的data2的值也跟着變化:

改變data2的值,相應的data1的值也跟着變化:

4、完整代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <cpn :number1="num1" :number2="num2"
       @num1change="num1change"
       @num2change="num2change"></cpn>
</div>

<template id="cpn">
  <div>
    <h2>props1: {{number1}}</h2>
    <h2>data1: {{dnumber1}}</h2>
<!--    <input type="text" v-model="dnumber1">-->
    <input type="text" v-bind:value="dnumber1" @input="num1Input">
    <h2>props2: {{number2}}</h2>
    <h2>data2: {{dnumber2}}</h2>
    <input type="text" :value="dnumber2" @input="num2Input">
<!--    <input type="text" v-model="dnumber2">-->
  </div>
</template>

<script src="../js/vue.js"></script>
<script>
  const  app = new Vue({
    el: '#app',
    data: {
      num1: 1,
      num2: 0
    },
    methods: {
      num1change(value) {
        this.num1 = parseFloat(value)
      },
      num2change(value) {
        this.num2 = parseInt(value)
      }
    },
    components: {
      cpn: {
        template: '#cpn',
        props: {
          number1: Number,
          number2: Number
        },
        data() {
          return {
            dnumber1: this.number1,
            dnumber2: this.number2
          }
        },
        methods: {
          num1Input(event) {
            // 1、將Input輸入框的值複製到dnumber1中
            this.dnumber1 = event.target.value;
            // 2、通過$emit發出事件改變父組件的值
            this.$emit('num1change', this.dnumber1)  // 通過$emit改變父組件的值
            // 3、同時修改dnumber2的值
            this.dnumber2 = this.dnumber1 * 100;  // 改變值
            this.$emit('num2change', this.dnumber2)  // 再次傳出去
          },
          num2Input(event) {
            this.dnumber2 = event.target.value;
            this.$emit('num2change', this.dnumber2)
            this.dnumber1 = this.dnumber2 / 100;  // 改變值
            this.$emit('num1change', this.dnumber1)  // 再次傳出去
          }
        }
      }
    }
  })
</script>

</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章