diff --git a/.gitignore b/.gitignore index b4a9415240..ea50b40700 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ Network Trash Folder Temporary Items .apdisk +# IDE, editors +.idea/ + ### Node ### # Logs logs diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 495605c288..a90686361f 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -611,7 +611,7 @@ export default defineConfigWithTheme({ text: 'MIT License', link: 'https://opensource.org/licenses/MIT' }, - copyright: `Copyright © 2014-${new Date().getFullYear()} Evan You` + copyright: `Bản quyền © 2014-${new Date().getFullYear()} Evan You` } }, diff --git a/.vitepress/theme/components/Home.vue b/.vitepress/theme/components/Home.vue index eb0e73cc2f..d21c959bbf 100644 --- a/.vitepress/theme/components/Home.vue +++ b/.vitepress/theme/components/Home.vue @@ -6,17 +6,16 @@ import SponsorsGroup from './SponsorsGroup.vue'; ``` -[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlYWN0aXZlLCBjb21wdXRlZCB9IGZyb20gJ3Z1ZSdcblxuY29uc3QgYXV0aG9yID0gcmVhY3RpdmUoe1xuICBuYW1lOiAnSm9obiBEb2UnLFxuICBib29rczogW1xuICAgICdWdWUgMiAtIEFkdmFuY2VkIEd1aWRlJyxcbiAgICAnVnVlIDMgLSBCYXNpYyBHdWlkZScsXG4gICAgJ1Z1ZSA0IC0gVGhlIE15c3RlcnknXG4gIF1cbn0pXG5cbi8vIGEgY29tcHV0ZWQgcmVmXG5jb25zdCBwdWJsaXNoZWRCb29rc01lc3NhZ2UgPSBjb21wdXRlZCgoKSA9PiB7XG4gIHJldHVybiBhdXRob3IuYm9va3MubGVuZ3RoID4gMCA/ICdZZXMnIDogJ05vJ1xufSlcbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxwPkhhcyBwdWJsaXNoZWQgYm9va3M6PC9wPlxuICA8c3Bhbj57eyBwdWJsaXNoZWRCb29rc01lc3NhZ2UgfX08L3NwYW4+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0ifQ==) +[Thử trong Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlYWN0aXZlLCBjb21wdXRlZCB9IGZyb20gJ3Z1ZSdcblxuY29uc3QgYXV0aG9yID0gcmVhY3RpdmUoe1xuICBuYW1lOiAnSm9obiBEb2UnLFxuICBib29rczogW1xuICAgICdWdWUgMiAtIEFkdmFuY2VkIEd1aWRlJyxcbiAgICAnVnVlIDMgLSBCYXNpYyBHdWlkZScsXG4gICAgJ1Z1ZSA0IC0gVGhlIE15c3RlcnknXG4gIF1cbn0pXG5cbi8vIGEgY29tcHV0ZWQgcmVmXG5jb25zdCBwdWJsaXNoZWRCb29rc01lc3NhZ2UgPSBjb21wdXRlZCgoKSA9PiB7XG4gIHJldHVybiBhdXRob3IuYm9va3MubGVuZ3RoID4gMCA/ICdZZXMnIDogJ05vJ1xufSlcbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxwPkhhcyBwdWJsaXNoZWQgYm9va3M6PC9wPlxuICA8c3Bhbj57eyBwdWJsaXNoZWRCb29rc01lc3NhZ2UgfX08L3NwYW4+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0ifQ==) -Here we have declared a computed property `publishedBooksMessage`. The `computed()` function expects to be passed a getter function, and the returned value is a **computed ref**. Similar to normal refs, you can access the computed result as `publishedBooksMessage.value`. Computed refs are also auto-unwrapped in templates so you can reference them without `.value` in template expressions. +Ở đây chúng ta đã khai báo một thuộc tính computed `publishedBooksMessage`. Hàm `computed()` nhận vào một hàm getter (hàm dùng để lấy giá trị), và giá trị được trả về là một **computed ref (tham chiếu)**. Tương tự như các ref thông thường, bạn có thể truy cập giá trị của nó thông qua `publishedBooksMessage.value`. Khi dùng trong template, `ref`sẽ được unwrap tự động nên bạn có thể tham chiếu tới nó mà không cần `.value`. -A computed property automatically tracks its reactive dependencies. Vue is aware that the computation of `publishedBooksMessage` depends on `author.books`, so it will update any bindings that depend on `publishedBooksMessage` when `author.books` changes. +Một thuộc tính computed sẽ tự động theo dõi các phụ thuộc có tính reactive. Vue biết rằng giá trị của `publishedBooksMessage` phụ thuộc vào `author.books`, nên nó sẽ cập nhật mọi ràng buộc vào `publishedBooksMessage` khi `author.books` thay đổi. -See also: [Typing Computed](/guide/typescript/composition-api.html#typing-computed) +Xem thêm: [Đặt kiểu cho thuộc tính computed](/guide/typescript/composition-api.html#typing-computed) -## Computed Caching vs Methods +## So sánh computed được cache và method -You may have noticed we can achieve the same result by invoking a method in the expression: +Có thể bạn đã để ý rằng chúng ta có thể đạt được kết quả tương tự bằng cách dùng gọi một phương thức: ```vue-html

{{ calculateBooksMessage() }}

@@ -162,9 +162,9 @@ function calculateBooksMessage() { -Instead of a computed property, we can define the same function as a method. For the end result, the two approaches are indeed exactly the same. However, the difference is that **computed properties are cached based on their reactive dependencies.** A computed property will only re-evaluate when some of its reactive dependencies have changed. This means as long as `author.books` has not changed, multiple access to `publishedBooksMessage` will immediately return the previously computed result without having to run the getter function again. +Chúng ta có thể định nghĩa chính hàm của thuộc tính computed dạng một phương thức. Hai cách tiếp cận đều cho kết quả hoàn toàn như nhau. Tuy nhiên, điều khác biệt ở đây là **các thuộc tính computed được cache dựa trên những sự phụ thuộc có tính reactive của nó.** Một thuộc tính computed sẽ chỉ được tính lại khi một số sự phụ thuộc của nó thay đổi. Điều này có nghĩa là miễn `author.books` không thay đổi, thì mọi lần truy cập vào `publishedBooksMessage` đều ngay lập tức trả về kết quả đã được tính toán trước đó mà không chạy lại hàm getter. -This also means the following computed property will never update, because `Date.now()` is not a reactive dependency: +Điều này cũng có nghĩa là thuộc tính computed dưới đây sẽ không bao giờ được cập nhật, bởi vì `Date.now()` không phải là một sự phụ thuộc có tính reactive.
@@ -186,13 +186,13 @@ const now = computed(() => Date.now())
-In comparison, a method invocation will **always** run the function whenever a re-render happens. +Trong khi đó, một lệnh gọi phương thức sẽ **luôn** chạy hàm đó bất cứ khi nào việc render lại xảy ra. -Why do we need caching? Imagine we have an expensive computed property `list`, which requires looping through a huge array and doing a lot of computations. Then we may have other computed properties that in turn depend on `list`. Without caching, we would be executing `list`’s getter many more times than necessary! In cases where you do not want caching, use a method call instead. +Tại sao chúng ta cần cache? Giả sử ta có một thuộc tính computed là `list`, thuộc tính này đòi hỏi lặp qua một mảng khổng lồ và thực hiện rất nhiều phép tính. Tiếp theo đó, chúng ta có thể có những thuộc tính computed khác phụ thuộc vào `list`. Nếu không có cache, chúng ta sẽ phải thực thi hàm getter của `list` nhiều hơn mức cần thiết rất nhiều! Trong những trường hợp bạn không muốn cache, hãy sử dụng phương thức thay vì thuộc tính computed. -## Writable Computed +## Thuộc tính computed có thể ghi -Computed properties are by default getter-only. If you attempt to assign a new value to a computed property, you will receive a runtime warning. In the rare cases where you need a "writable" computed property, you can create one by providing both a getter and a setter: +Mặc định thì những thuộc tính computed là chỉ đọc (chỉ có getter). Nếu bạn cố ghi giá trị mới vào một thuộc tính computed, bạn sẽ nhận được một cảnh báo runtime. Trong các trường hợp hãn hữu bạn cần một thuộc tính computed có thể ghi, bạn có thể cung cấp cả getter và setter cho nó:
@@ -220,7 +220,7 @@ export default { } ``` -Now when you run `this.fullName = 'John Doe'`, the setter will be invoked and `this.firstName` and `this.lastName` will be updated accordingly. +Giờ khi bạn chạy `this.fullName = 'John Doe'`, setter sẽ được gọi rồi `this.firstName` và `this.lastName` sẽ được cập nhật tương ứng.
@@ -247,16 +247,16 @@ const fullName = computed({ ``` -Now when you run `fullName.value = 'John Doe'`, the setter will be invoked and `firstName` and `lastName` will be updated accordingly. +Giờ khi bạn chạy `fullName.value = 'John Doe'`, setter sẽ được gọi rồi `firstName` vả `lastName` sẽ được cập nhật tương ứng. -## Best Practices +## Lời khuyên khi dùng thuộc tính computed -### Getters should be side-effect free +### Getter không nên có hiệu ứng phụ -It is important to remember that computed getter functions should only perform pure computation and be free of side effects. For example, don't make async requests or mutate the DOM inside a computed getter! Think of a computed property as declaratively describing how to derive a value based on other values - its only responsibility should be computing and returning that value. Later in the guide we will discuss how we can perform side effects in reaction to state changes with [watchers](./watchers). +Điều quan trọng cần phải nhớ là hàm getter chỉ nên thực hiện duy nhất một việc tính toán đơn thuần và không có hiệu ứng phụ. Ví dụ, đừng tạo một request đồng bộ hoặc thay đổi DOM bên trong một hàm getter! Hãy xem thuộc tính computed như một khai báo về cách để lấy giá trị dựa trên những giá trị khác – nó chỉ có trách nhiệm tính toán và trả về giá trị đó mà thôi. Ở phần sau của hướng dẫn, chúng ta sẽ thảo luận về cách để thực hiện một hiệu ứng phụ dựa trên sự thay đổi của state bằng [watcher](./watchers). -### Avoid mutating computed value +### Tránh thay đổi các giá trị đã tính -The returned value from a computed property is derived state. Think of it as a temporary snapshot - every time the source state changes, a new snapshot is created. It does not make sense to mutate a snapshot, so a computed return value should be treated as read-only and never be mutated - instead, update the source state it depends on to trigger new computations. +Giá trị được trả về từ một thuộc tính computed là trạng thái được suy luận ra. Hãy xem nó như một snapshot (ảnh chụp) tạm thời – mỗi khi các trạng thái mà nó phụ thuộc bị thay đổi, thì một snapshot mới được tạo ra. Việc thay đổi một snapshot là không hợp lý, vậy một giá trị được trả về bởi computed nên được xem là chỉ đọc và không bao giờ bị thay đổi – thay vào đó, hãy cập nhật trạng thái mà nó phụ thuộc để kích hoạt những tính toán mới. diff --git a/src/guide/essentials/conditional.md b/src/guide/essentials/conditional.md index 8f70c3c271..0783d32356 100644 --- a/src/guide/essentials/conditional.md +++ b/src/guide/essentials/conditional.md @@ -1,4 +1,4 @@ -# Conditional Rendering +# Render theo điều kiện @@ -84,9 +84,9 @@ To get started with Vue without a build step, simply copy the following code int ``` -The above example uses the global build of Vue where all APIs are exposed under the global `Vue` variable. +Ví dụ trên sử dụng bản build global của Vue, với toàn bộ API có sẵn (exposed) trong biến toàn cục `Vue`. -While the global build works, we will be primarily using [ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) syntax throughout the rest of the documentation for consistency. In order to use Vue over native ES modules, use the following HTML instead: +Tuy hoàn toàn có thể dùng bản build global của Vue, trong suốt phần còn lại của tài liệu này chúng ta chủ yếu sẽ sử dụng cú pháp [ES module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) cho nhất quán. Để sử dụng Vue với ES module, hãy dùng đoạn HTML sau: ```html ``` -Notice how we can import directly from `'vue'` in our code - this is made possible by the `