- Chuyên mục khác :
- PHP và Laravel
- ·
- Database - Git - Linux
- ·
- Vuejs
- ·
- Lập Trình Web
- Getting Started
- Vue.js là gì?
- Các cách sử dụng Vue khác nhau
- Khám phá các lựa chọn thay thế Vue
- Xây dựng ứng dụng đầu tiên chỉ bằng JavaScript
- Xây dựng lại ứng dụng với Vue
- Basics & Core Concepts - DOM Interaction with Vue
- Module Introduction
- Connecting Vue App Instances
- Interpolation và Data Binding
- Binding Attributes với v-bind Directive
- Understanding methods in Vue Apps
- Working with Data inside of a Vue App
- Outputting Raw HTML Content with v-html
- Event Binding v-on
- Events & Methods
- Using the Native Event Object
- Event Modifiers
- Two-Way Binding
- Methods used for Data Binding
- Computed Properties
- Working with Watchers
- Methods vs Computed Properties vs Watchers
- v-bind and v-on Shorthands
- Dynamic Styling with Inline Styles
- CSS Classes Dynamically
- Rendering Conditional Content & Lists
- Conditions & Lists Starting-Setup
- v-if, v-else and v-else-if
- v-show
- Rendering Lists of Data
- Vue Behind The Scenes
- Understand Vue Reactivity
- Understanding Templates
- Working with Refs
- How Vue Updates the DOM
- Vue App Lifecycle
- Components
- Workflow with Vue3 CLI
- Vue Initial Steps & Structure
- Inspecting the Vue Project
- Vue extentions
- Vue Component
- Props
- $emit and Listening to Events
- Method of array object in JavaScript
- Provide + Inject
- Global vs Local Components
- Scoped Styles
- Slots
- Dynamic Components and Keeping Dynamic Components Alive
- Teleporting Elements
- Fragments
- The Vue Style Guide
Trong quá trình phát triển ứng dụng Vue.js, việc chia sẻ dữ liệu giữa các thành phần có thể trở nên phức tạp, đặc biệt là khi có sự lồng ghép sâu của các thành phần con bên trong các thành phần cha. Để giải quyết vấn đề này một cách linh hoạt và hiệu quả, Vue.js cung cấp một cặp tính năng mạnh mẽ gọi là provide và inject.
Provide là một tính năng cho phép các thành phần cha cung cấp dữ liệu cho tất cả các thành phần con của chúng mà không cần phải truyền dữ liệu qua props. Thay vì đó, dữ liệu được "cung cấp" và tự động truy cập được bởi các thành phần con.
Inject là một tính năng cho phép các thành phần con "tiêm" dữ liệu từ thành phần cha của chúng, mà không cần phải truyền props xuống từ thành phần cha. Các thành phần con chỉ cần khai báo các khóa mà họ muốn tiêm và Vue.js sẽ tự động tìm kiếm và tiêm dữ liệu phù hợp từ các thành phần cha.
Với cặp tính năng này, việc chia sẻ dữ liệu giữa các thành phần trở nên dễ dàng hơn và giảm thiểu sự phức tạp trong quản lý trạng thái của ứng dụng Vue.js. Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách sử dụng provide và inject để xây dựng các ứng dụng Vue.js linh hoạt và dễ bảo trì.
Cách Dùng:
1. Provide:
- provide là một thuộc tính của thành phần cha, được sử dụng để cung cấp dữ liệu cho tất cả các thành phần con của nó.
- Bạn có thể cung cấp một đối tượng hoặc một hàm trả về một đối tượng.
// ParentComponent.vue
<script>
export default {
provide() {
return {
sharedData: 'Dữ liệu chia sẻ từ cha'
};
}
}
</script>
2. Inject:
- inject là một thuộc tính của thành phần con, được sử dụng để chứa các khóa mà thành phần con muốn lấy từ thành phần cha.
- Vue sẽ tự động tìm kiếm các khóa đã được cung cấp trong cây thành phần cha.
// ChildComponent.vue
<script>
export default {
inject: ['sharedData'],
mounted() {
console.log(this.sharedData); // In ra "Dữ liệu chia sẻ từ cha"
}
}
</script>
3. Inject function + event:
- Khi người dùng sử dụng event để truyền dữ liệu lên parent cha và cập nhập dữ liệu đó.
- Vue sẽ tự động tìm kiếm các hàm đã được cung cấp trong cây thành phần cha và thực thi chúng.
<!-- ChildComponent.vue -->
<template>
<div>
<button @click="selectTopic(10)">Trigger Event</button>
</div>
</template>
<script>
export default {
inject: ["selectTopic"]
}
</script>
// ParentComponent.vue
<script>
export default {
provide() {
return {
sharedData: 'Dữ liệu chia sẻ từ cha',
selectTopic: this.activateTopic
};
},
methods: {
activateTopic(topicId) {
// xử lý data ở đây
},
},
}
</script>
Ví dụ trong trường hợp bạn không sử dụng Provide và Inject chúng ta phải truyền qua từng props và emit trong tất cả component con để chuyền qua lại dữ liệu.
<!-- ParentComponent.vue -->
<template>
<div>
<active-element
:topic-title="activeTopic && activeTopic.title"
:text="activeTopic && activeTopic.fullText"
></active-element>
<knowledge-base :topics="topics" @select-topic="activateTopic"></knowledge-base>
</div>
</template>
<script>
export default {
data() {
return {
topics: [
{
id: 'basics',
title: 'The Basics',
description: 'Core Vue basics you have to know',
fullText:
'Vue is a great framework and it has a couple of key concepts: Data binding, events, components and reactivity - that should tell you something!',
},
{
id: 'components',
title: 'Components',
description:
'Components are a core concept for building Vue UIs and apps',
fullText:
'With components, you can split logic (and markup) into separate building blocks and then combine those building blocks (and re-use them) to build powerful user interfaces.',
},
],
activeTopic: null,
};
},
methods: {
activateTopic(topicId) {
this.activeTopic = this.topics.find((topic) => topic.id === topicId);
},
},
};
</script>
<!-- ChildComponent.vue (knowledge-base) -->
<template>
<section>
<h2>Select a Topic</h2>
<knowledge-grid :topics="topics" @select-topic="$emit('select-topic', $event)"></knowledge-grid>
</section>
</template>
<script>
export default {
props: ['topics'],
emits: ['select-topic'],
};
</script>
<!-- ChildComponent.vue (knowledge-grid) -->
<template>
<ul>
<knowledge-element
v-for="topic in topics"
:key="topic.id"
:id="topic.id"
:topic-name="topic.title"
:description="topic.description"
@select-topic="$emit('select-topic', $event)"
></knowledge-element>
</ul>
</template>
<script>
export default {
props: ['topics'],
emits: ['select-topic']
};
</script>
<!-- ChildComponent.vue (knowledge-element) -->
<template>
<li>
<h3>{{ topicName }}</h3>
<p>{{ description }}</p>
<button @click="$emit('select-topic', id)">Learn More</button>
</li>
</template>
<script>
export default {
props: ['id', 'topicName', 'description'],
emits: ['select-topic'],
};
</script>
Nhìn ví dụ trên các bạn thấy khá là phức tạp đúng không nếu trong trường hợp mà nó còn có nhiều component con hơn nữa thì đúng là khó có thể kiểm soát được đúng không chính vì thế Provide và Inject đã giúp chúng ta xử lý vấn đề này một cách đơn giản hơn.
Để sử dụng Provide và Inject chó ví dụ trên tà làm như sau:
<!-- ParentComponent.vue -->
<template>
<div>
<active-element
:topic-title="activeTopic && activeTopic.title"
:text="activeTopic && activeTopic.fullText"
></active-element>
<knowledge-base :topics="topics" @select-topic="activateTopic"></knowledge-base>
</div>
</template>
<script>
export default {
data() {
return {
topics: {...}
activeTopic: null,
};
},
provide() {
return {
topics: this.topics,
selectTopic: this.activateTopic
}
},
methods: {
activateTopic(topicId) {
this.activeTopic = this.topics.find((topic) => topic.id === topicId);
},
},
};
</script>
<!-- ChildComponent.vue (knowledge-base) -->
<template>
<section>
<h2>Select a Topic</h2>
<knowledge-grid></knowledge-grid>
</section>
</template>
<script>
export default {
};
</script>
<!-- ChildComponent.vue (knowledge-grid) -->
<template>
<ul>
<knowledge-element
v-for="topic in topics"
:key="topic.id"
:id="topic.id"
:topic-name="topic.title"
:description="topic.description"
></knowledge-element>
</ul>
</template>
<script>
export default {
inject: ['topics'],
};
</script>
<!-- ChildComponent.vue (knowledge-element) -->
<template>
<li>
<h3>{{ topicName }}</h3>
<p>{{ description }}</p>
<button @click="selectTopic(id)">Learn More</button>
</li>
</template>
<script>
export default {
props: ['id', 'topicName', 'description'],
inject: ['selectTopic']
};
</script>
Lưu Ý:
- Khi sử dụng provide và inject, hãy cẩn thận với việc quản lý trạng thái và đảm bảo rằng dữ liệu được chia sẻ theo cách an toàn và đúng đắn.
- Nên sử dụng provide và inject cho những trường hợp cần thiết, như chia sẻ dữ liệu toàn cục hoặc cấu hình ứng dụng, nhưng hãy cân nhắc sử dụng props cho các trường hợp cần chia sẻ dữ liệu giữa các thành phần cụ thể.
Bình luận (0)