父子組件間單向數據流的解決辦法

上一篇:父子組件間傳值

在上一篇中講解了父子組件之間是如何傳值的,如果子組件需要改變傳過來的數據供自己使用,或者想在子組件中改變傳過來的數據并同步到父組件,那么直接改肯定是不行的,如果你這么做了,Vue 會在控制臺給出警告。

對應這兩種情況,解決方式如下:

先創建項目并運行

vue init webpack-simple template
cd template
npm i
npm run dev

一、 子組件需要改變傳過來的數據供自己使用
1. 定義一個局部變量,并用 props 的值來初始化它

在 App.vue 中

<template>
    <div class="hello">
        <h3>我是 App 父組件</h3>
        <h4>訪問自己的數據:{{msg}},{{name}},{{user.id}}</h4>
        <hr>
        <!-- 1. 在調用子組件時,綁定想要獲取的父組件中的數據 -->
        <Hello :message="msg"></Hello>
    </div>
</template>

<script>
// 引入 Hello 組件
import Hello from './assets/components/Hello.vue'
export default {
  data(){
    return {
      msg:'父組件',
      name:'tom',
      age:'22',
      user:{
        id:1234,
        userName:'Jack'
      }
    }
  },
  // 注冊 Hello 組件
  components:{
    Hello
  }
}
</script>

在 Hello.vue 中

<template>
    <div class="hello">
        <h3>我是 hello 子組件</h3>
        <!-- 在頁面中直接渲染即可 -->
        <h4>訪問父組件中的數據: {{msg}}</h4>
        <button @click="change">改變父組件的數據</button>
    </div>
</template>

<script>
export default {
    // 2. 在子組件內部,使用 props 選項聲明獲取的數據,即接收來自父組件中的數據
    props:['message'],
    data(){
        return {
            // 定義一個局部變量,并用 props 的值來初始化它
            msg:this.message
        }
    },
    methods:{
        // 定義一個方法,來觸發改變父組件的數據
        change(){
            this.msg = '我改變了父組件的數據'
        }
    }
}
</script>

效果圖:


子組件改變父組件的數據
2. 定義一個計算屬性,處理 prop 的值并返回:

在 Hello.vue 中改動

<script>
export default {
    // 2. 在子組件內部,使用 props 選項聲明獲取的數據,即接收來自父組件中的數據
    props:['message'],
    data(){
        return {
            // 定義一個局部變量,并用 props 的值來初始化它
            msg:this.message
        }
    },
    computed:{
        // 定義一個方法,來觸發改變父組件的數據
        change(){
            return this.msg = '我改變了父組件的數據'
        }
    }
}
</script>

當頁面渲染成功自動完成計算


二、子組件中改變傳過來的數據并同步到父組件
1. 使用 sync 修飾符,它會被擴展為一個自動更新父組件屬性的 v-on 監聽器

在 App.vue 中把 template 的內容更改為

<template>
    <div class="hello">
        <h3>我是 App 父組件</h3>
        <h4>訪問自己的數據:{{msg}}</h4>
        <hr>
        <!-- 1. 在調用子組件時,綁定想要獲取的父組件中的數據 -->
        <!-- .sync 會被擴展為一個自動更新父組件屬性的 v-on 監聽器 -->
        <Hello :message.sync="msg"></Hello>
    </div>
</template>

在 Hello.vue 中更改為

<template>
    <div class="hello">
        <h3>我是 hello 子組件</h3>
        <!-- 在頁面中直接渲染即可 -->
        <h4>訪問父組件中的數據: {{message}}</h4>
        <button @click="change">改變父組件的數據</button>
    </div>
</template>

<script>
export default {
    // 2. 在子組件內部,使用 props 選項聲明獲取的數據,即接收來自父組件中的數據
    props:['message'],
    methods:{
        change(){
            // 使用 .sync 時,需要顯式的觸發一個更新事件
            // update 為固定寫法,后面跟將要被改變的數據對象,接著寫替換的數據
            this.$emit('update:message','我改變了父組件的數據')
        }
    }
}
</script>

效果為:


2. 可以將父組件中的數據包裝成對象或數組,然后在子組件中修改對象的屬性

在 App.vue 中

<template>
    <div class="hello">
        <h3>我是 App 父組件</h3>
        <h4>訪問自己的數據:{{user.userName}}</h4>
        <hr>
        <!-- 2. 在調用子組件時,綁定想要獲取的父組件中的數據 -->
        <Hello :user="user"></Hello>
    </div>
</template>

<script>
// 引入 Hello 組件
import Hello from './assets/components/Hello.vue'
export default {
  data(){
    return {
      // 1. 在父組件中把數據寫成對象的形式
      user:{
        id:1234,
        userName:'Jack'
      }
    }
  },
  // 注冊 Hello 組件
  components:{
    Hello
  }
}
</script>

在 Hello.vue 中

<template>
    <div class="hello">
        <h3>我是 hello 子組件</h3>
        <!-- 5. 在頁面中直接渲染即可 -->
        <h4>訪問父組件中的數據: {{user.userName}}</h4>
        <button @click="change">改變父組件的數據</button>
    </div>
</template>

<script>
export default {
    // 3. 在子組件內部,使用 props 選項聲明獲取的數據,即接收來自父組件中的數據
    props:['message','user'],
    methods:{
        // 4.直接修改 user 對象中的數據
        change(){
            this.user.userName = 'Tom'
        }
    }
}
</script>

效果如下:


我們是不允許直接修改父組件傳過來的數據或對象的,而這種方法更改的是對象中的屬性,因為對象是引用類型,指向同一內存空間,所以可以實現此效果。推薦使用該方式

下一篇:非父子組件間通信

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容