vue元件之間的資料傳遞

富途web開發團隊發表於2018-03-25

最近在整理專案中程式碼,在元件之間資料傳遞遇到了問題,所以做了這次總結,如有不對的地方,望指正。

父元件如何將資料傳到子元件中

父元件可以通過Prop傳遞資料到子元件中。

這裡需要注意的是:

  • Prop 是單向繫結的:當父元件的屬性變化時,將傳導給子元件,但是反過來不會。這是為了防止子元件無意間修改了父元件的狀態,來避免應用的資料流變得難以理解。

  • 每次父元件更新時,子元件的所有 Prop 都會更新為最新值。這意味著你不應該在子元件內部改變 prop。如果你這麼做了,Vue 會在控制檯給出警告。

在兩種情況下,我們很容易忍不住想去修改 prop 中資料:

  • Prop 作為初始值傳入後,子元件想把它當作區域性資料來用;

解決方法:定義一個區域性變數,並用 prop 的值初始化它:

props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}    
複製程式碼
  • Prop 作為原始資料傳入,由子元件處理成其它資料輸出。

解決方法: 定義一個計算屬性,處理 prop 的值並返回:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
複製程式碼

PS:上邊的內容是vue文件裡邊有說的,我只是把自己在專案中遇到的問題抽出來了。連結

栗子:

// 父元件 index.vue
<template>
    <div class="content">
        <child :lists="lists"></child>
    </div>
</template>
<script>
    import child from './child.vue';
    export default {
        components: {
            child
        },
        data() {
            return {
                lists: []
            };
        },
        mounted() {
            this.lists = [{
                name: '01',
                content: 'hi,'
            }, {
                name: '02',
                content: 'my name is Ellyliang'
            }];
        }
    };
</script>

// 子元件 child.vue
<template>
    <ul class="content">
       <li v-for="(list, index) in getLists" :key="index" v-html="list.name + list.content"></li>
    </ul>
</template>
<script>
    export default {
        props: ['lists'],
        data() {
            return {
                getLists: this.lists
            };
        },
        mounted() {
            this.getLists.push({
                name: '03',
                content: '不要在乎內容,我就是測試'
            });
        }
    };
</script>
複製程式碼

子元件如何將資料傳到父元件中

子元件可通過vm.$emit將資料傳遞給父元件

vm.$emit是啥

觸發當前例項上的事件。附加引數都會傳給監聽器回撥。 連結

栗子:

// 父元件 index.vue
<template>
    <div class="content">
        <child :lists="lists" @listenToChild="getChildMsg"></child>
    </div>
</template>
<script>
    import child from './child.vue';
    export default {
        components: {
            child
        },
        data() {
            return {
                lists: []
            };
        },
        mounted() {
            this.lists = [{
                name: '01',
                content: 'hi,'
            }, {
                name: '02',
                content: 'my name is Ellyliang'
            }];
        },
        methods: {
            getChildMsg(val) {
                alert(val);  // 'hello'
            }
        }
    };
</script>

// 子元件 child.vue
<template>
    <div class="content">
        <ul class="lists">
            <li v-for="(list, index) in getLists" :key="index" v-html="list.name + list.content"></li>
        </ul>
    </div>
</template>
<script>
    export default {
        props: ['lists'],
        data() {
            return {
                getLists: this.lists
            };
        },
        mounted() {
            this.getLists.push({
                name: '03',
                content: '不要在乎內容,我就是測試'
            });
            
            setTimeout(() => {
                this.$emit('listenToChild', 'hello');
            }, 15000);
        }
    };
</script>
複製程式碼

子元件給父元件傳資料是不是也很方便。實現方法是就是在子元件中$emit資料,然後在父元件中通過事件@事件名接收值。

Event Bus

事件巴士這種方法,不僅能處理父子元件傳遞,子父元件傳遞,還是處理平級元件之間的數值傳遞。其實現方法就是在全域性new一個vue例項,然後傳值給bus, 就是let bus = new vue();。通過這個全域性的bus中的$emit, $on等等去實現資料的傳遞。這樣處理有個問題,由於event bus處理資料傳遞很方便,不管在哪裡都可以傳遞,這樣導致濫用,從而導致程式碼很難去理解。

Event Bus實現

let bus = new Vue();
// 觸發元件 A 中的事件
bus.$emit('id-selected', 1);
// 在元件 B 建立的鉤子中監聽事件
bus.$on('id-selected', function (id) {
// ...
});
複製程式碼

具體元件的封裝和使用,可參考vue-bus

其它方式

除了以上3種方法,還有就是通過vuex去處理資料的傳遞,但是我還沒有接觸,大家要感興趣,自己去學習。

相關文章