如何將非同步資料傳入 Prop ?
栏目: JavaScript · 发布时间: 6年前
内容简介:假如資料是從Vue 2.5.17Vue CLI 3.0.5
假如資料是從 App.vue
透過 API 抓取資料,然後透過 Prop 傳進 Component,最後再讀取 Prop 寫入 Component 的 Data,這看似平常的過程,若是同步資料則完全不是問題,但因為資料是從 API 來,為非同步 Promise,寫法則沒有想像中單純。
Version
Vue 2.5.17
Vue CLI 3.0.5
錯誤寫法
App.vue
<template> <div id="app"> <todo-list :source="todos"> </todo-list> </div> </template> <script> import TodoList from './components/todo-list.vue'; import { fetchTodos } from './api/todos.api'; const mounted = function() { const response = res => this.todos = res.data.slice(0, 5); fetchTodos() .then(response); }; const components = { TodoList, }; const data = function() { return { todos: [], }; }; export default { name: 'app', components, data, mounted, }; </script> <style> </style>
12 行
const mounted = function() { const response = res => this.todos = res.data.slice(0, 5); fetchTodos() .then(response); };
在 mounted
hook 透過 API 抓取資料。
第 3 行
<todo-list :source="todos"> </todo-list>
將 todos
傳進 todo-list
的 source
prop。
todo-list.vue
<template> <div id="todo-list"> <input type="text" v-model="input"> <button @click="addItem">Add</button> <ul> <li v-for="(todo, index) in todos" @click="finishItem(index)" :key="index"> {{ todo.title }}, {{ todo.completed }} </li> </ul> </div> </template> <script> const finishItem = function(index) { this.todos[index].completed = !this.todos[index].completed; }; const addItem = function() { const elem = { title: this.input, completed: false, }; this.todos = [...this.todos, elem]; }; const props = [ 'source', ]; const data = function() { return { input: '', todos: this.source, }; }; const methods = { finishItem, addItem, }; export default { name: 'todo-list', props, data, methods, }; </script> <style scoped> </style>
30 行
const data = function() { return { input: '', todos: this.source, }; };
在 data()
將 source
prop 指定給 todos
。
這種寫法在若 prop 資料為同步,則為標準寫法;但若是非同步資料,則 todos
永遠為 []
。
因為 Promise 為非同步,會在同步執行完後才執行,也就是 todo-list
component 的 data()
會先執行,最後才執行 Promise,因此 todos
永遠為 []
。
正確寫法
todo-list.vue
<template> <div id="todo-list"> <input type="text" v-model="input"> <button @click="addItem">Add</button> <ul> <li v-for="(todo, index) in todos" @click="finishItem(index)" :key="index"> {{ todo.title }}, {{ todo.completed }} </li> </ul> </div> </template> <script> const finishItem = function(index) { this.todos[index].completed = !this.todos[index].completed; }; const addItem = function() { const elem = { title: this.input, completed: false, }; this.todos = [...this.todos, elem]; }; const source = function(value) { this.todos = value; }; const props = [ 'source', ]; const data = function() { return { input: '', todos: this.source, }; }; const watch = { source, }; const methods = { finishItem, addItem, }; export default { name: 'todo-list', props, data, watch, methods, }; </script> <style scoped> </style>
41 行
const watch = { source, };
由於 Promise 會最後執行,因此必須對 source
prop 開 watch。
26 行
const source = function(value) { this.todos = value; };
將 Promise 最後執行改變 source
prop 時,會執行 watch 的 source()
,再由此 function 去改變 todos
data。
如此 component 就能收到 prop 傳進來的非同步資料了。
Conclusion
- 寫 ECMAScript 只要碰到非同步 Promise,就要考慮到其是最後執行,因此不能使用同步的方式思考
Sample Code
完整的範例可以在我的 GitHub 上找到
以上所述就是小编给大家介绍的《如何將非同步資料傳入 Prop ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。