LÀM THẾ NÀO ĐỂ TRUYỀN DỮ LIỆU GIỮA CÁC COMPONENT TRONG VUEJS?

04/11/2021 52
lam the nao de truyen du lieu giua cac component trong vuejs feature
CODEWELL

Khi làm việc với VueJS, chắc chắn bạn sẽ làm việc với các đơn vị thành phần (được gọi là component). Chính vì vậy, việc hiểu rõ cách giao tiếp giữa các component trong VueJS với nhau là hết sức cần thiết. 

1. MỞ ĐẦU

Vue.js (gọi tắt là Vue) là một framework linh động dùng để xây dựng giao diện người dùng (user interfaces), được thiết kế cho phép và khuyến khích phát triển ứng dụng theo từng bước. 

Nếu kết hợp với những kĩ thuật hiện đại như SFC (single file components)các thư viện hỗ trợ, Vue có thể đáp ứng được dễ dàng nhu cầu xây dựng những ứng dụng một trang (SPA – Single-Page Applications) với độ phức tạp cao.

Khi làm việc với VueJS, chắc chắn bạn sẽ làm việc với các đơn vị thành phần (được gọi là component). Chính vì vậy, việc hiểu rõ cách giao tiếp giữa các component với nhau là hết sức cần thiết. 

Cũng như các framework khác như Angular hay React, VueJS có những cách thức thực hiện riêng của nó. Hãy cùng tìm hiểu Làm thế nào để truyền dữ liệu giữa các component trong VueJS? trong bài dưới đây.

 

2. CÁC CÁCH TRUYỀN DỮ LIỆU GIỮA CÁC COMPONENT TRONG VUEJS

Chúng ta có 4 cách để truyền data giữa các component trong VueJS, đó là: 

  • Truyền data từ component cha xuống component con qua Props
  • Truyền từ component con lên component cha thông qua Emit event 
  • Truyền giữa các component không có quan hệ thông qua Event bus
  • Sử dụng Store của VueX (tương tự store trong Redux)

Bây giờ hãy cùng đi qua cách thực hiện của từng phương pháp này nhé.

 

Truyền từ component cha xuống component con thông qua Props

Hãy cùng xem ví dụ  về các truyền component trong VueJS thông qua Props như bên dưới. Chúng ta có một component cha, đóng vai trò bao bọc một component con.

<template>
  <div id="app">
    <ComponentFirst msg="Welcome to Your Vue.js App"/>
    //OR <ComponentFirst :msg="Welcome to Your Vue.js App">
    //OR <ComponentFirst v-bind:msg="Welcome to Your Vue.js App"></ComponentFirst>
  </div>
</template>

<script>
import ComponentFirst from './components/componentFirst';

export default {
  name: 'App',
    components: {
    ComponentFirst
  }
}
</script>

Ta sẽ tiến hành truyền đoạn msg xuống cho component con của nó, đây là phần props mà bạn có thể đặt tên tùy ý. Nó có thể truyền các loại data xuống component con, khi thay đổi thông tin trên component cha thì component con cũng sẽ tự động cập nhật lại thông tin tương ứng.

<template>
  <div>{{msg}}</div>
</template>

<script>
export default {
  name: "Component first",
  props: {
    msg: String
  }
};
</script>

Trên đây là đoạn code của component con nhận được data từ component cha truyền cho. 

Hãy lưu ý rằng props chỉ được truyền một chiều từ component cha xuống component con – không có chiều ngược lại. Một component cha có thể truyền data này tới nhiều component con, vì thế một component không thể có quyền thay đổi data trên component cha được. 

Đây chính là tính toàn vẹn dữ liệu. Điều này giống như trên ReactJS, bạn chỉ có thể truyền data 1 chiều xuống, không thể trực tiếp thay đổi data.

Khi so sánh với Angular 2+, có thể thấy Vue.js và React có phương thức truyền props đơn giản và dễ thực hiện hơn, vì không cần khai báo thêm nhiều.

 

Truyền data từ component con lên component cha trong VueJS

Đầu tiên, chúng ta hãy cùng xem đoạn code sau của component cha. Hãy chú ý đến cách nhận event trên đoạn code này nhé:

<template>
  <div id="app">
    <ComponentFirst @inputData="updateMessage"/>
    <h3>{{message}}</h3>
  </div>
</template>

<script>
import ComponentFirst from './components/componentFirst';

export default {
  name: 'App',
  components: {
    ComponentFirst
  },
  data() {
    return {
      message: 'Message default.'
    }
  },
  methods: {
    updateMessage(mes) {
      this.message = mes;
    }
  }
}
</script>

 

Ở Component cha chúng ta sẽ cần nhập @inputData để tương thích với key mà chúng ta sẽ đẩy(emit) lên từ component con. Tiếp theo đó, ta sẽ gắn một methods ở component cha để có thể “lắng nghe” khi component con emit một sự kiện lên. 

Khi component con emit lên, nó có thể truyền thêm data hoặc không, component cha cũng có thể chứa tham số hoặc không có cũng được.

Dưới đây là đoạn code thực hiện emit data từ component con:

<template>
  <div>
    <input
      placeholder="Enter Text Here"
      v-model="tempMessage"
    />
    <div>
      <button @click="sendMessage">@Emit event</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "ComponentFirst",
  data() {
    return {
      tempMessage: ''
    }
  },
  methods: {
    sendMessage() {
      this.$emit('inputData', this.tempMessage);
      this.tempMessage = '';
    }
  }
};
</script>

 

Hãy so sánh một chút về phương pháp này ở Angular và React.

Ở cách truyền dữ liệu này, nếu sử dụng Angular ta sẽ cần cả @Output và emit, trong khi React thì lại không cần khai báo emit thêm. Đối với VueJS, ta vẫn cần emit nhưng cách thực hiện lại tinh gọn hơn Angular.

 

Truyền data giữa các component trong VueJS với Eventbus:

EventBus là một thư viện open-source cho Java hoặc Android, giúp đơn giản hóa việc giao tiếp giữa các component, hay các phần của một app với nhau.

Có thể hiểu bản chất Eventbus như một service bên ngoài để lưu tạm data. Nó sẽ lưu thông tin ở đó, cho phép một bên khác truy cập vào để theo dõi dự thay đổi. Nếu có thay đổi, Eventbus sẽ tiến hành tiếp nhận sự kiện đó. 

lam the nao de truyen du lieu giua cac component trong vuejs eventbus
Nguyên lý hoạt động của EventBuss

 

Trên thực tế, còn khi thực sự ứng dụng Eventbus vào code thì thì với mỗi Framework lại có cách triển khai khác nhau.

Hãy ví dụ với trường hợp dưới đây. Đoạn code nằm ở root, nơi mà bạn đặt hai component.

<template>
  <div id="app">
    <ComponentFirst />
    <hr />
    <ComponentSecond />
  </div>
</template>

<script>
import ComponentFirst from './components/component-first';
import ComponentSecond from './components/component-second';

export default {
  name: 'App',
  components: {
    ComponentFirst,
    ComponentSecond
  },
  data() {
    return {
      message: 'Message default.'
    }
  }
}
</script>

 

Hãy lưu ý rằng điều kiện để ta thể truyền data giữa 2 component chính là 2 component này phải đang cùng “sống” (tồn tại). Nếu như một component đang tồn tại và component còn lại bị xóa thì sẽ không thể truyền data được.

Tiếp theo, đoạn code bên dưới chính là phần Eventbus trung chuyển. Nhìn nó khá đơn giản, được biểu hiện như một instance của Vue.

import Vue from 'vue';

const EventBus = new Vue();

export default EventBus;

 

Đoạn code bên dưới chính là ComponentFirst, nơi mà bạn bắt đầu truyền data đến giao thức Eventbus.

<template>
  <div>
    <input
      placeholder="Enter Text Here"
      v-model="tempMessage"
    />
    <div>
      <button @click="sendMessage">Emit data</button>
    </div>
  </div>
</template>

<script>
import EventBus from './../event-bus';

export default {
  name: "ComponentFirst",
  data() {
    return {
      tempMessage: ''
    }
  },
  methods: {
    sendMessage() {
      EventBus.$emit('inputData', this.tempMessage);
      this.tempMessage = '';
    }
  }
};
</script>

 

Ở đoạn code này, hãy lưu ý tên khi thực hiện $emit phải trùng với tên khi nhận event.

Tiếp theo là code từ phía nhận data của Eventbus. Chúng ta phải thông qua mounted() để lắng nghe khi mà data được truyền đi.

<template>
  <div>Component B: {{msg}}</div>
</template>

<script>
import EventBus from './../event-bus';

export default {
  name: "ComponentSecond",
  data() {
    return {
      msg: ''
    }
  },
  mounted() {
    EventBus.$on('inputData' ,payLoad => {
      this.msg = payLoad;
    });
  }
};
</script>

 

Truyền data giữa các component thông qua VueX

VueX là một state management pattern + library – thư viện giúp quản lý trạng thái các component trong VueJS, đây là nơi lưu trữ tập trung dữ liệu cho tất cả các component trong một ứng dụng. 

Nếu như bạn đã làm việc với các Framework khác rồi, thì VueX có thể hiểu giống như Ngrx với Angular 2+, Redux với ReactJS. 

Bản chất của VueX cũng là nơi để lưu trữ(store) dữ liệu và sẽ có thể sử dụng để lắng nghe – nhận lại data. Nó tổng quát hơn và mạnh mẽ hơn cách dùng service rất nhiều.

Cũng như khi dùng EventBus, bạn hãy chắc chắn rằng cả 2 component của chúng ta đều đang được tồn tại nhé.

Khi sử dụng VueX, bạn hãy hiểu nó như là 1 giai đoạn nơi lưu trữ tất cả những data singleton (data ít thay đổi) hoặc dùng để gắn action(event) truyền data từ đó tới các phần khác trong app.

Để sử dụng, đầu tiên hãy cài đặt nó vào app của mình. Ở đây chúng ta sẽ dùng yarn, nhưng bạn cũng có thể dùng npm nếu thích:

  • yarn add vuex
  • npm install vuex

Tiếp đó chúng ta hãy tạo một folder store và viết store.

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    message: ''
  },
  getters: {
    MESSAGE: state => {
      return state.message;
    }
  },
  mutations: {
    SET_MESSAGE: (state, payload) => {
      state.message = payload;
    }
  },
  actions: {}
});

 

Như các bạn có thể thấy, chúng ta vừa tạo ra một Store để sử dụng cho toàn app. Sau khi tạo, hãy lên config nó trong main.js để Vue có thể tiếp nhận được.

import Vue from 'vue';
import App from './App.vue';

import store from './store';

new Vue({
  store,
  render: h => h(App),
}).$mount('#app');

 

Phần dưới đây là code bên Component nguồn. Chúng ta sẽ commit một data đến cho Store và nó sẽ cài data này vào stage.

<template>
  <div>
    <div>Component first</div>
    <input
      placeholder="Enter Text Here"
      v-model="tempMessage"
    />
    <div>
      <button @click="sendMessage">Emit data</button>
    </div>
  </div>
</template>

<script>

export default {
  name: "ComponentFirst",
  data() {
    return {
      tempMessage: ''
    }
  },
  methods: {
    sendMessage() {
      this.$store.commit("SET_MESSAGE", this.tempMessage);
      this.tempMessage = '';
    }
  }
};
</script>

 

Tiếp đó ở component đích, ta sẽ dùng component để lắng nghe. Nếu như data có sự thay đổi thì nó sẽ render lại ra view.

<template>
  <div>
    <div>Component second: {{msg}}</div>
  </div>
</template>

<script>

export default {
  name: "ComponentSecond",
  computed: {
    msg() {
      return this.$store.getters.MESSAGE;
    }
  }
};
</script>

3. Kết luận

Trên đây là 4 cách để giao tiếp giữa các component trong VueJS. Bạn hãy lựa chọn cách xử lý phù hợp với từng trường hợp của bản thân nhé. 

Tuy nhiên, nếu dự án của bạn có sử dụng VueX thì hãy cố gắng sử dụng nó. Không chỉ sử dụng để truyền dữ liệu giữa các component, nó còn là một công cụ tuyệt vời để quản lý dữ liệu trong VueJS. 

 

Tư liệu tham khảo
Bài viết có có sử dụng thông tin từ các bài dưới đây:
# Sharing Data Between Components in Vue.js 1
# How to share data between components in VueJS
# Passing Data Between Vue Components 1
# A simple EventBus to communicate between Vue.js components

Nguyễn Xuân Sơn – CO-WELL Asia


Xem thêm các bài viết khác của CO-WELL Asia tại đây