Reactjs 和 Vuejs 建立 Component 的方式比對

最近這陣子剛好有機會接觸到 Vuejs,之前覺得會寫一點 Reactjs 應該就可以騙吃騙喝了(誤),但是這陣子感受到蠻多人好像都開始寫 Vuejs,不稍微碰一下感覺會落伍啊!其實學 Vuejs 是為了在 Laravel 前端上使用,之前稍微看過一些文章感覺真的蠻棒的!

以下的文章或許會有錯誤,I'm Vuejs rookie!希望在讀文章的各位不要鞭的太用力,若有錯誤歡迎指正!

Create Simple Todo List

How to create Reactjs Todo List Component:

const Todo = ({ todo }) => (
<li>{todo.text}</li>
);
const TodoList = ({ todos }) => {
const todoNode = todos.map(todo => <Todo todo={todo} key={todo.id} />);
return (
<ul>{todoNode}</ul>
);
};
class App extends Component {
constructor() {
super();
this.state = {
todos: [
{ id: 1, text: 'Write Some Code' },
{ id: 2, text: 'Running' },
{ id: 3, text: 'Play Baskebtall' },
]
};
}
render() {
return (
<div>
<TodoList todos={this.state.todos} />
</div>
);
}
}

How to create Vuejs Todo List Component:

<div id="app">
<ul>
<todo-item v-for="todo in todos" :key="todo.id" :todo="todo"></todo-item>
</ul>
</div>
Vue.component('todo-item', {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`,
});
new Vue({
el: '#app',
data: {
todos: [
{ id: 1, text: 'Write Some Code' },
{ id: 2, text: 'Running' },
{ id: 3, text: 'Play Baskebtall' },
]
}
});

觀察 Reactjs 和 Vuejs 他們是如何傳遞 props

Reactjs 部分

Reactjs 主要透過自己特殊的 jsx 語法,看到 class App return 的地方:

<TodoList todos={this.state.todos} />
  1. 在 App constructor 初始化的 todos state
  2. <TodoList todos={this.state.todos} /> 的 tag todos,這是要傳到 child component 的 props name,可以透過這樣的方式不斷的往下傳遞 props,除了傳值之外也可以傳 function。
  3. const TodoList = ({ todos }) => { ... } 我們 destructuring 傳下來的 props,再把這些 todos 做 map 往 <Todo /> 傳下去。

Vuejs 部分

Vuejs 主要是從 HTML 上的 attribute 特性來實現的:

<todo-item v-for="todo in todos" :key="todo.id" :todo="todo"></todo-item>
  1. 看到 Vuejs 自己特殊的 v-for attribute,這裡就是 iterator todos 的 Object,也是我們熟悉的 for-in

  2. :key="todo.id"v-bind:key="todo.id" 的縮寫,後面的 :todo 也是。

  • 註:這裡的 :todo 是動態的,它會受到 parent component 影響,更多請參考官方文件說明
  1. todo-item 是由我們自己所定義的 Component,可以看到第二個參數物件內的 props
Vue.component('todo-item', {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`,
});
  1. props: ['todo'] 是由 parent :todo 傳下來的 ,所以我們可以在 child component 內的 props 來接收。

我們在 root component 內已經先初始化 todos 的資料:

new Vue({
el: '#app',
data: {
todos: [
{ id: 1, text: 'A' },
{ id: 2, text: 'B' },
{ id: 3, text: 'C' }
]
}
});

加入新增 Todo 的方法

Reactjs 部分

// 新增一個 functional component
const InputTodo = ({ addTodo }) => {
let inputText;
return (
<div>
<input ref={input => inputText = input} />
<button onClick={() => {
addTodo(inputText.value);
inputText.value = '';
}}>Add</button>
</div>
);
};
// 在 App 新增一個 `addTodo` method
addTodo = (todo) => {
const todoLength = this.state.todos.length;
this.state.todos.push({
id: todoLength + 1,
text: todo,
});
this.setState({ todos: this.state.todos });
}
//
// 在 App return 內把 InputTodo Component 加入,
// 並把 `this.addTodo` function 作為 props 傳下去
<InputTodo addTodo={this.addTodo} />

Vuejs 部分

  1. 在 HTML 內加入一個 inputbutton
  2. input 使用 v-model 來 binding。
  3. button 監聽 onClick 事件,當被點擊時,觸發並使用 addTodo 這個 method 來處理。
<input v-model="text" />
<button @click="addTodo">Add</button>
  1. data 新增一個 text,主要是和 inputv-model="text" 做 binding,當 input 輸入值改變時,也會改變 data.text
  2. methods 是當一些 event 被觸發時,要對應到哪個 method 來做處理,這裡我們在 button 設定 @click="addTodo",所以在 methods 也要有對應的 addTodo method。
// 更新 JavaScript 部分
data: {
text: '',
todos: [
{ id: 1, text: 'Write Some Code' },
{ id: 2, text: 'Running' },
{ id: 3, text: 'Play Baskebtall' },
]
},
methods: {
addTodo() {
let todoLength = this.todos.length;
this.todos.push({
id: todoLength + 1,
text: this.text,
});
this.text = '';
}
},

大概可以稍微感受一下 Vuejs,不過看了一下官方文件,不過還蠻多很棒的特性都還沒有使用到啊!