← index

Reactjs 和 Vuejs 建立 Component 的方式比對

Comparing react and vue to create 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,不過看了一下官方文件,不過還蠻多很棒的特性都還沒有使用到啊!