Các loại giao tiếp
Khi thiết kế một ứng dụng Vue (hoặc trên thực tế, bất kỳ ứng dụng dựa trên thành phần nào), có các kiểu giao tiếp khác nhau tùy thuộc vào mối quan tâm mà chúng ta đang giải quyết và chúng có các kênh giao tiếp riêng.
Logic kinh doanh: đề cập đến mọi thứ cụ thể cho ứng dụng của bạn và mục tiêu của nó.
Logic trình bày: bất kỳ thứ gì mà người dùng tương tác hoặc kết quả từ sự tương tác từ người dùng.
Hai mối quan tâm này có liên quan đến các loại giao tiếp này:
- Trạng thái ứng dụng
- Cha-con
- Cha mẹ trẻ em
- Anh chị em ruột
Mỗi loại nên sử dụng đúng kênh liên lạc.
Kênh thông tin liên lạc
Kênh là một thuật ngữ lỏng lẻo mà tôi sẽ sử dụng để chỉ các triển khai cụ thể để trao đổi dữ liệu xung quanh ứng dụng Vue.
Đạo cụ: Logic trình bày giữa cha mẹ và con cái
Kênh giao tiếp đơn giản nhất trong Vue để giao tiếp trực tiếp giữa Cha mẹ và Con cái . Nó chủ yếu nên được sử dụng để chuyển dữ liệu liên quan đến logic trình bày hoặc một tập hợp dữ liệu bị hạn chế xuống hệ thống phân cấp.
Refs và phương pháp: Trình bày chống mẫu
Khi sử dụng một phương thức hỗ trợ để cho phép một đứa trẻ xử lý một sự kiện từ cha mẹ là không hợp lý, việc thiết lập một ref
thành phần con và gọi các phương thức của nó là tốt.
Đừng làm như vậy, đó là một kiểu chống đối. Suy nghĩ lại về kiến trúc thành phần và luồng dữ liệu của bạn. Nếu bạn thấy mình muốn gọi một phương thức trên thành phần con từ cha mẹ, có lẽ đã đến lúc nâng trạng thái lên hoặc xem xét các cách khác được mô tả ở đây hoặc trong các câu trả lời khác.
Sự kiện: Logic trình bày giữa con-cha mẹ
$emit
và $on
. Kênh giao tiếp đơn giản nhất để giao tiếp trực tiếp giữa Con và Cha. Một lần nữa, nên được sử dụng cho logic trình bày.
Xe buýt sự kiện
Hầu hết các câu trả lời đều đưa ra các lựa chọn thay thế tốt cho bus sự kiện, đây là một trong những kênh liên lạc có sẵn cho các thành phần ở xa hoặc bất cứ thứ gì trên thực tế.
Điều này có thể trở nên hữu ích khi chuyển các đạo cụ khắp nơi từ xa lên đến các thành phần con lồng nhau sâu sắc, hầu như không có thành phần nào khác cần những thành phần này ở giữa. Sử dụng một cách tiết kiệm cho dữ liệu được lựa chọn cẩn thận.
Hãy cẩn thận: Việc tạo tiếp theo của các thành phần tự ràng buộc với bus sự kiện sẽ bị ràng buộc nhiều lần - dẫn đến nhiều trình xử lý được kích hoạt và rò rỉ. Cá nhân tôi chưa bao giờ cảm thấy cần một bus sự kiện trong tất cả các ứng dụng trang đơn mà tôi đã thiết kế trước đây.
Phần sau minh họa cách một sai lầm đơn giản dẫn đến rò rỉ trong đó Item
thành phần vẫn kích hoạt ngay cả khi bị xóa khỏi DOM.
// A component that binds to a custom 'update' event.
var Item = {
template: `<li>{{text}}</li>`,
props: {
text: Number
},
mounted() {
this.$root.$on('update', () => {
console.log(this.text, 'is still alive');
});
},
};
// Component that emits events
var List = new Vue({
el: '#app',
components: {
Item
},
data: {
items: [1, 2, 3, 4]
},
updated() {
this.$root.$emit('update');
},
methods: {
onRemove() {
console.log('slice');
this.items = this.items.slice(0, -1);
}
}
});
<script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script>
<div id="app">
<button type="button" @click="onRemove">Remove</button>
<ul>
<item v-for="item in items" :key="item" :text="item"></item>
</ul>
</div>
Hãy nhớ xóa người nghe trong destroyed
hook vòng đời.
Cửa hàng tập trung (Logic kinh doanh)
Vuex là con đường đi cùng với Vue để quản lý nhà nước . Nó cung cấp nhiều hơn chỉ là các sự kiện và nó đã sẵn sàng cho ứng dụng quy mô đầy đủ.
Và bây giờ bạn hỏi :
[S] tôi có nên tạo cửa hàng của vuex cho mỗi lần giao tiếp nhỏ không?
Nó thực sự tỏa sáng khi:
- xử lý logic kinh doanh của bạn,
- giao tiếp với phần phụ trợ (hoặc bất kỳ lớp lưu trữ dữ liệu nào, như lưu trữ cục bộ)
Vì vậy, các thành phần của bạn có thể thực sự tập trung vào những thứ mà chúng có nghĩa là quản lý giao diện người dùng.
Nó không có nghĩa là bạn không thể sử dụng nó cho logic thành phần, nhưng tôi sẽ phạm vi logic đó đến một mô-đun Vuex có không gian tên chỉ với trạng thái giao diện người dùng toàn cầu cần thiết.
Để tránh đối phó với một mớ hỗn độn lớn của mọi thứ ở trạng thái toàn cầu, cửa hàng nên được tách biệt trong nhiều mô-đun không gian tên.
Các loại thành phần
Để sắp xếp tất cả các thông tin liên lạc này và để dễ dàng sử dụng lại, chúng ta nên nghĩ về các thành phần như hai loại khác nhau.
- Vùng chứa ứng dụng cụ thể
- Thành phần chung
Một lần nữa, điều đó không có nghĩa là một thành phần chung phải được sử dụng lại hoặc không thể sử dụng lại một vùng chứa ứng dụng cụ thể, nhưng chúng có các trách nhiệm khác nhau.
Vùng chứa ứng dụng cụ thể
Đây chỉ là thành phần Vue đơn giản bao bọc các thành phần Vue khác (vùng chứa chung hoặc các vùng chứa ứng dụng cụ thể khác). Đây là nơi giao tiếp với cửa hàng Vuex và vùng chứa này sẽ giao tiếp thông qua các phương tiện khác đơn giản hơn như đạo cụ và trình nghe sự kiện.
Những vùng chứa này thậm chí có thể không có phần tử DOM gốc nào cả và để cho các thành phần chung xử lý các tương tác của người dùng và tạo khuôn mẫu.
phạm vi bằng cách nào đó events
hoặc stores
khả năng hiển thị cho các thành phần anh chị em
Đây là nơi xảy ra phạm vi. Hầu hết các thành phần không biết về cửa hàng và thành phần này (chủ yếu) nên sử dụng một mô-đun cửa hàng không gian tên với một tập hợp giới hạn getters
và actions
được áp dụng với trình trợ giúp liên kết Vuex được cung cấp .
Thành phần chung
Chúng sẽ nhận dữ liệu của chúng từ các đạo cụ, thực hiện các thay đổi trên dữ liệu cục bộ của chính chúng và tạo ra các sự kiện đơn giản. Hầu hết thời gian, họ không nên biết một cửa hàng Vuex tồn tại.
Chúng cũng có thể được gọi là vùng chứa vì trách nhiệm duy nhất của chúng có thể là gửi đến các thành phần UI khác.
Liên lạc anh chị em
Vì vậy, sau tất cả những điều này, chúng ta nên giao tiếp giữa hai thành phần anh em như thế nào?
Dễ hiểu hơn với một ví dụ: giả sử chúng ta có một hộp nhập liệu và dữ liệu của nó phải được chia sẻ trên ứng dụng (anh chị em ở các vị trí khác nhau trong cây) và tồn tại với một chương trình phụ trợ.
Bắt đầu với tình huống xấu nhất , thành phần của chúng tôi sẽ kết hợp giữa trình bày và logic nghiệp vụ.
// MyInput.vue
<template>
<div class="my-input">
<label>Data</label>
<input type="text"
:value="value"
:input="onChange($event.target.value)">
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
value: "",
};
},
mounted() {
this.$root.$on('sync', data => {
this.value = data.myServerValue;
});
},
methods: {
onChange(value) {
this.value = value;
axios.post('http://example.com/api/update', {
myServerValue: value
})
.then((response) => {
this.$root.$emit('update', response.data);
});
}
}
}
</script>
Để tách biệt hai mối quan tâm này, chúng ta nên bọc thành phần của mình trong một vùng chứa ứng dụng cụ thể và giữ logic trình bày thành thành phần đầu vào chung của chúng ta.
Thành phần đầu vào của chúng tôi hiện có thể sử dụng lại và không biết về phụ trợ cũng như anh chị em.
// MyInput.vue
// the template is the same as above
<script>
export default {
props: {
initial: {
type: String,
default: ""
}
},
data() {
return {
value: this.initial,
};
},
methods: {
onChange(value) {
this.value = value;
this.$emit('change', value);
}
}
}
</script>
Vùng chứa ứng dụng cụ thể của chúng tôi hiện có thể là cầu nối giữa logic nghiệp vụ và giao tiếp trình bày.
// MyAppCard.vue
<template>
<div class="container">
<card-body>
<my-input :initial="serverValue" @change="updateState"></my-input>
<my-input :initial="otherValue" @change="updateState"></my-input>
</card-body>
<card-footer>
<my-button :disabled="!serverValue || !otherValue"
@click="saveState"></my-button>
</card-footer>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import { NS, ACTIONS, GETTERS } from '@/store/modules/api';
import { MyButton, MyInput } from './components';
export default {
components: {
MyInput,
MyButton,
},
computed: mapGetters(NS, [
GETTERS.serverValue,
GETTERS.otherValue,
]),
methods: mapActions(NS, [
ACTIONS.updateState,
ACTIONS.updateState,
])
}
</script>
Vì các hành động của cửa hàng Vuex liên quan đến giao tiếp phụ trợ, vùng chứa của chúng tôi ở đây không cần biết về axios và phụ trợ.
$emit
kết hợp vớiv-model
để thi đua.sync
. tôi nghĩ bạn nên đi theo cách