- Học Vue
-
Hệ sinh thái
Hỗ trợ
Công cụ
Thư viện chính thức
Tin tức
Tài nguyên
- Đội ngũ
- Hỗ trợ Vue
- Ngôn ngữ
Hướng dẫn
Khái niệm cơ bản
- Cài đặt
- Giới thiệu
- Đối tượng Vue
- Cú pháp template
- Computed property và watcher
- Binding cho class và style
- Render theo điều kiện
- Render danh sách
- Xử lí sự kiện
- Ràng buộc form input
- Cơ bản về component
Components In-Depth
- Đăng kí Component
- Props
- Custom Events
- Slots
- Dynamic & Async Components
- Handling Edge Cases
Hiệu ứng chuyển động
- Transition cho enter/leave & danh sách
- Transition cho trạng thái
Tái sử dụng & kết hợp
- Mixin
- Directive tùy biến
- Các hàm render & JSX
- Plugin
- Filter
Công cụ
- Triển khai cho môi trường production
- Single File Components
- Unit test
- TypeScript Support
Mở rộng quy mô ứng dụng
- Routing
- Quản lí trạng thái
- Render ở phía server
Bên trong Vue
- Reactivity in Depth
Thông tin thêm
- Comparison with Other Frameworks
- Join the Vue.js Community!
- Đội ngũ
Computed property và watcher
Computed property
Computed property có thể hiểu là một “thuộc tính được tính toán.” Để cho nhất quán, chúng tôi sẽ giữ nguyên cụm từ computed property
.
Viết biểu thức trực tiếp trong template rất tiện, nhưng chỉ dành cho những biểu thức có tính toán đơn giản. Những biểu thức phức tạp được viết theo cách đó sẽ khiến template cồng kềnh và khó bảo trì. Ví dụ:
<div id="example"> |
Đến đây, template không còn đơn giản và mang tính khai báo (declarative) nữa. Bạn sẽ phải mất chút thời gian thì mới nhận ra được message
đã bị đảo ngược. Càng tệ hơn khi bạn sử dụng biến message
đảo ngược này nhiều lần trong code.
Đó là lí do tại sao đối với bất kì logic nào phức tạp, bạn nên sử dụng computed property.
Ví dụ cơ bản
<div id="example"> |
var vm = new Vue({ |
Kết quả là:
Thông điệp ban đầu: "{{ message }}"
Thông điệp bị đảo ngược (computed): "{{ reversedMessage }}"
Ở đây chúng ta khai báo một computed property là reversedMessage
. Hàm mà chúng ta đã cung cấp sẽ được sử dụng như một hàm getter cho thuộc tính vm.reversedMessage
:
console.log(vm.reversedMessage) // => 'ngược xuôi thuyền đợi bến đông người' |
Bạn có thể mở console và thử chạy đối tượng vm mẫu ở trên. Giá trị của vm.reversedMessage
luôn phụ thuộc vào giá trị của vm.message
.
Bạn có thể ràng buộc dữ liệu (data-bind) cho computed property trong template một cách bình thường như những thuộc tính khác. Vue biết được vm.reversedMessage
phụ thuộc vào vm.message
nên sẽ cập nhật bất kì ràng buộc (binding) nào phụ thuộc vào vm.reversedMessage
khi vm.message
thay đổi. Điểm hay nhất ở đây là chúng ta tạo ra được mối liên hệ giữa các thành phần phụ thuộc (dependency): các hàm getter của computed thì không bị hiệu ứng phụ (side effect), chính điều đó giúp dễ hiểu và dễ kiểm tra.
Computed caching và phương thức
Bạn có lẽ đã nhận ra chúng ta cũng có thể đạt được cùng một kết quả bằng cách sử dụng một phương thức:
<p>Thông điệp bị đảo ngược: "{{ reverseMessage() }}"</p> |
// trong component |
Thay vì sử dụng computed property, chúng ta cũng có thể dùng một phương thức thay thế. Nếu xét về kết quả cuối cùng thì hai cách tiếp cận này thât ra chỉ là một. Tuy nhiên, sự khác biệt ở đây là computed property được cache lại dựa vào những những thành phần phụ thuộc (dependency). Một computed property chỉ được tính toán lại khi những thành phần phụ thuộc của chúng thay đổi. Điều này có nghĩa: miễn là giá trị của message
không thay đổi, thì những truy cập tới computed reversedMessage
sẽ ngay lập tức trả về kết quả được tính toán trước đó mà không phải chạy lại hàm một lần nữa.
Điểu này cũng có nghĩa là computed property dưới đây sẽ không bao giờ cập nhật, bởi vì Data.now()
không phải là một thành phần phụ thuộc phản ứng (reactive dependency) :
computed: { |
Để so sánh, một phương phương thức luôn được gọi khi có một sự kiện render lại (re-render) xảy ra.
Tại sao chúng ta lại cần phải cache? Thử tưởng tượng chúng ta có một computed property A có nhiều thao tác tính toán trên một mảng dữ liệu lớn. Chúng ta lại có nhiều computed property phụ thuộc vào A. Nếu không cache lại, chúng ta phải thực thi hàm getter của A nhiều hơn mức cần thiết rất nhiều! Trong trường hợp bạn không muốn cache, hãy sử dụng một phương thức thay thế.
Computed và watched
Vue cung cấp một cách khái quát hơn để quan sát và phản ứng (react) lại những thay đổi trên dữ liệu: watch property. Khi bạn có một số dữ liệu cần được thay đổi dựa trên những dữ liệu khác, bạn rất dễ lạm dụng watch
- nhất là nếu bạn có nền tảng về AngularJS. Tuy nhiên, thường thì bạn nên dùng computed
thay vì watch
. Hãy xem ví dụ sau:
<div id="demo">{{ fullName }}</div> |
var vm = new Vue({ |
Đoạn code phía trên theo hướng mệnh lệnh và lặp lại. Hãy so sánh với phiên bản dùng computed property:
var vm = new Vue({ |
Cách này tốt hơn nhiều đúng không?
Computed Setter
Những computed property mặc định chỉ có getter, nhưng bạn cũng có thể cung cấp setter nếu cần thiết:
// ... |
Bây giờ, khi bạn gán vm.fullName = 'John Doe'
, thì setter sẽ được gọi, vm.firstName
và vm.lastName
sẽ được cập nhật tương ứng.
Watcher
Computed property thích hợp cho hầu hết các trường hợp, nhưng cũng có lúc cần tới những watcher tùy biến. Đó là lí do tại sao Vue cung cấp một cách khái quát hơn để phản ứng lại với việc thay đổi dữ liệu trong watch
. Cách sử dụng này rất hữu ích khi bạn muốn thực hiện những tính toán không đồng bộ và tốn kém liên quan đến việc thay đổi dữ liệu.
Ví dụ:
<div id="watch-example"> |
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> |
Kết quả:
Hãy hỏi một câu hỏi yes/no:
{{ answer }}
Trong trường hợp này, sử dụng watch
cho phép chúng ta thực hiện những tính toán không đồng bộ (ví dụ: truy cập tới một API), giới hạn việc chúng ta thường xuyên thực hiện tính toán đó và gán trạng thái trung gian cho tới khi chúng ta có được kết quả cuối cùng. Nếu dùng computed property bạn sẽ không làm được những chuyện này.
Ngoài tùy chọn watch
, bạn cũng có thể sử dụng vm.$watch API.