React フレームワーク と Vue フレームワーク の比較について、両者で同じプログラムを書き、そのコード実装の過程を比較し、どれほどの違いがあるのかを見てみましょう。
転載元:https://blog.csdn.net/csdnnews/article/details/81880378
原文:https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-e9a1ae8077fd
著者紹介:Sunil Sandhu、Web フルスタックエンジニア + 空想家。
翻訳者:安翔、編集者:屠敏
ご存知の通り、Vue と React は現在非常に有名なフロントエンドフレームワークです。私は仕事で Vue を頻繁に使用しているため、非常に深く理解しています。同時に、React にも好奇心を持っており、学んでみたいと思っています。
そこで、私は React のドキュメントを読み、いくつかのビデオチュートリアルを見ました。これらの資料は素晴らしいものでしたが、私が本当に理解したいのは React と Vue の違いです。「違い」とは、両者が仮想 DOM を持っているかどうかや、どのようにページをレンダリングするかではなく、コードの観点からこの二つの違いを説明してくれる人がいることを望んでいます。私は、Vue または React の初心者が両者の違いをよりよく理解できるような、これらの違いを説明する記事を探していました。
残念ながら、そのような記事は見つかりませんでした。そこで、私は自分で Vue と React の違いを比較する必要があると気づきました。自力での過程を記録するために、この文章を書きました。
1. 目標#
私は、ユーザーがリスト内の項目を追加および削除できる標準的なタスク管理アプリケーションを構築します。この二つのアプリケーションは、デフォルトの CLI(コマンドラインインターフェース)を使用して構築され、React は create-react-app を使用し、Vue は vue-cli を使用します。
二つのアプリケーションの外観は以下の通りです:
二つのアプリケーションの CSS コードはほぼ同じですが、これらのコードの位置には違いがあります。これを考慮して、二つのアプリケーションのファイル構造を見てみましょう:
あなたは、彼らの構造がほぼ完全に同じであることに気づくでしょう。唯一の違いは、React アプリには三つの CSS ファイルがあるのに対し、Vue アプリには CSS ファイルがないことです。これは、React の create-react-app コンポーネントがスタイルを保存するための付属ファイルを必要とするのに対し、Vue CLI は全包方法を採用し、スタイルが実際のコンポーネントファイル内で宣言されるためです。
二つの異なる戦略から得られる結果は同じであり、開発者はすぐにこれら二つの異なる戦略を習得できると信じています。開発者は自分の好みに応じて選択できます。CSS の構築方法について開発コミュニティで多くの議論が行われているのを耳にするでしょう。以上のことから、私たちは二つの CLI に従ってコード構造を列挙しました。
さらに議論を進める前に、典型的な Vue と React コンポーネントの外観を簡単に見てみましょう:
それでは、正式に始めましょう!詳細に入りましょう!
2. データの変更方法#
まず、「データの変更」の意味を理解する必要があります。これは少し学術的に聞こえますが、実際には非常に簡単で、すでに保存されているデータを変更することを指します。たとえば、ある人の名前の変数を「Jhon」から「Mark」に変更したい場合、「データの変更」操作を実行する必要があります。この点で、React と Vue の処理方法には違いがあります。Vue は本質的にデータオブジェクトを作成し、そのデータは自由に変更できます。一方、React は状態オブジェクトを作成し、データを変更するにはいくつかの追加操作が必要です。React が追加の操作を必要とする理由は後で詳しく説明します。それ以前に、Vue のデータオブジェクトと React の状態オブジェクトを見てみましょう:
vue データオブジェクト
React 状態オブジェクト
図からわかるように、同じデータを渡しましたが、マークアップ方法が異なります。したがって、初期データをコンポーネントに渡す方法は非常に似ています。しかし、前述のように、二つのフレームワークでデータを変更する方法には違いがあります。
たとえば、name: ‘Sunil’ というデータ要素があるとします。
Vue では、this.name を呼び出してそれを参照します。また、this.name ='John' を呼び出すことで更新することもできます。これにより、名前は「Jhon」に成功裏に変更されます。
React では、this.state.name を呼び出して同じデータを参照します。ここでの重要な違いは、this.state.name ='John' と単純に書くことはできないということです。なぜなら、React には制限メカニズムがあり、そのような単純な変更を防ぐからです。React では、次のように書く必要があります:this.setState ({name:'John'})。
これは基本的に Vue で実現した結果と同じですが、React の操作はより煩雑です。これは、Vue がデータを更新するたびに自動的に独自の setState バージョンを組み合わせるためです。簡単に言えば、React は setState を必要とし、その内部データを更新しますが、Vue にとっては、データオブジェクトの値を更新すると、変更意図が自動的に認識されます。では、なぜ React は簡略化せず、setState が必要なのでしょうか?Revanth Kumar がこれを説明しています:
「これは、React が状態が変化したときに特定のライフサイクルフックを再実行したいからです。たとえば、componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate などです。setState 関数を呼び出すと、状態が変更されたことがわかります。直接状態を変更すると、React は変更を追跡し、ライフサイクルフックを実行するためにより多くの作業をする必要があります。したがって、簡単にするために、React は setState を使用します。」
3. 新しいタスクを追加する#
React の実装方法#
createNewToDoItem = () => {
this.setState( ({ list, todo }) => ({
list: [
...list,
{
todo
}
],
todo: ''
})
);
};
React では、入力フィールドに value という名前の属性があります。この value は、いくつかの関数を使用して自動的に更新され、これらの関数は双方向バインディングを作成するために結びつけられています。入力フィールドに onChange イベントリスナーを追加することで、この形式の双方向バインディングを作成します。コードを見てみましょう:
<input type="text"
value={this.state.todo}
onChange={this.handleInput}/>
入力フィールドの値が変更されると、handleInput 関数が実行されます。この関数は、入力フィールド内の任意の内容を状態オブジェクトに設定することで、状態オブジェクトを更新します。handleInput 関数は次のようになります:
handleInput = e => {
this.setState({
todo: e.target.value
});
};
今、ユーザーがページ上の + ボタンを押して新しい項目を追加すると、createNewToDoItem 関数が this.setState を実行し、関数を渡します。この関数には二つのパラメータがあります。最初のパラメータは状態オブジェクトからの全リスト配列で、二番目のパラメータは handleInput 関数によって更新された todo です。次に、この関数は以前の全リストを含む新しいオブジェクトを返し、その末尾に todo を追加します。全リストはスプレッド演算子を使用して追加されます。
最後に、todo を空の文字列に設定し、それが自動的に入力フィールド内の value を更新します。
Vue の実装方法#
createNewToDoItem() {
this.list.push(
{
'todo': this.todo
}
);
this.todo = '';
}
Vue では、入力フィールドに v-model というハンドルがあります。これにより、双方向バインディングが実現されます。入力フィールドのコードは次の通りです:
<input type="text" v-model="todo"/>
v-model は、入力フィールドの内容を toDoItem というデータオブジェクトのキーにバインドします。ページが読み込まれると、toDoItem を空の文字列に設定します。たとえば:todo:' '。すでにデータが存在する場合、たとえば todo:' テキストを追加 ' の場合、入力フィールドは「テキストを追加」の入力内容を読み込みます。いずれにせよ、空の文字列として、入力フィールドに入力した任意のテキストは todo にバインドされます。これは実際には双方向バインディングです(入力フィールドはデータオブジェクトを更新でき、データオブジェクトは入力フィールドを更新できます)。
したがって、前述の createNewToDoItem () コードブロックを振り返ると、todo の内容をリスト配列に格納し、その後 todo を空の文字列に変更します。
4. タスクを削除する#
React の実装方法#
deleteItem = indexToDelete => {
this.setState(({ list }) => ({
list: list.filter((toDo, index) => index !== indexToDelete)
}));
};
deleteItem 関数は ToDo.js ファイルにありますが、ToDoItem.js ファイルからそれを参照するのも簡単です。deleteItem () 関数を prop として渡します:
<ToDoItem deleteItem={this.deleteItem.bind(this, key)}/>
これにより、その関数が子コンポーネントに渡され、アクセスできるようになります。this をバインドし、key パラメータを渡します。ユーザーが項目を削除するためにクリックすると、関数はどの ToDoItem がクリックされたかを key で区別します。その後、ToDoItem コンポーネント内で次のように実行します:
<div className=”ToDoItem-Delete” onClick={this.props.deleteItem}>-</div>
親コンポーネント内の関数を参照するには、this.props.deleteItem を参照するだけです。
Vue の実装方法#
onDeleteItem(todo){
this.list = this.list.filter(item => item !== todo);
}
Vue の実装方法は少し異なります。以下の三つのことを行う必要があります:
- まず、要素上で関数を呼び出します:
<div class=”ToDoItem-Delete” @click=”deleteItem(todo)”>-</div>
- 次に、emit 関数を作成し、それを子コンポーネントの内部メソッド(この場合は ToDoItem.vue)として定義します:
deleteItem(todo) {
this.$emit('delete', todo)
}
- その後、ToDo.vue の ToDoItem.vue を追加するときに、実際に関数を参照していることがわかります:
<ToDoItem v-for="todo in list"
:todo="todo"
@delete="onDeleteItem" // <-- これです :)
:key="todo.id" />
これがカスタムイベントリスナーと呼ばれるものです。これは、'delete' という文字列を使用したトリガーイベントをリッスンします。イベントをリッスンすると、onDeleteItem という関数がトリガーされます。この関数は ToDo.vue 内部にあり、ToDoItem.vue ではありません。前述のように、この関数はデータオブジェクト内の todo 配列をフィルタリングして、クリックされたタスクを削除します。
Vue の例で注意すべき点は、@click リスナー内で $emit 部分を書くことができ、これによりさらに簡単になります。次のように:
<div class=”ToDoItem-Delete” @click=”$emit(‘delete’, todo)”>-</div>
このようにすることで、3 ステップを 2 ステップに減らすことができます。
React の子コンポーネントは this.props を介して親関数にアクセスできますが、Vue では、子コンポーネントからイベントを発火させ、親コンポーネントがそのイベントを収集する必要があります。
5. イベントリスナーを渡す方法#
React の実装方法#
イベントリスナーは、シンプルなイベント(たとえばクリック)を処理するのが非常に直接的です。私たちはタスクのためにクリックイベントを作成し、新しいタスクを作成するためのコードは次の通りです:
<div className=”ToDo-Add” onClick={this.createNewToDoItem}>+</div>
非常にシンプルで、バニラ JS でインライン onClick を処理するのと同じです。前述のように、Enter ボタンを押すと、イベントリスナーを設定するのに時間がかかります。これは、入力タグが onKeyPress イベントを処理する必要があるため、コードは次の通りです:
<input type=”text” onKeyPress={this.handleKeyPress}/>
この関数は、'enter' キーが押されたことを認識すると、createNewToDoItem 関数をトリガーします。コードは次のようになります:
handleKeyPress = (e) => {
if (e.key === ‘Enter’) {
this.createNewToDoItem();
}
};
Vue の実装方法#
Vue のイベントリスナーはさらに直接的です。単純な @ 記号を使用するだけで、必要なイベントリスナーを構築できます。たとえば、クリックイベントリスナーを追加したい場合、コードは次の通りです:
<div class=”ToDo-Add” @click=”createNewToDoItem()”>+</div>
注意:@click は実際には v-on の省略形です。Vue のイベントリスナーは非常に強力で、.once などの属性を選択して、イベントリスナーが複数回トリガーされるのを防ぐことができます。さらに、多くのショートカットが含まれています。Enter ボタンを押すと、React ではイベントリスナーを作成するのに時間がかかりますが、新しいタスクを作成するために、Vue ではコードは次のようになります:
<input type=”text” v-on:keyup.enter=”createNewToDoItem”/>
6. データを子コンポーネントに渡す方法#
React の実装方法#
React では、props を子コンポーネントの作成時に渡します。たとえば:
<ToDoItem key={key} item={todo} />
ここでは、ToDoItem コンポーネントに二つの prop を渡しました。その後、子コンポーネント内で this.props を介してそれらを参照できます。したがって、item.todo prop にアクセスしたい場合は、this.props.item を呼び出すだけです。
Vue の実装方法#
Vue では、props を子コンポーネントの作成時に渡す方法は次の通りです:
<ToDoItem v-for="todo in list"
:todo="todo"
:key="todo.id"
@delete="onDeleteItem" />
これらを子コンポーネント内の props 配列に渡します。たとえば:props:['id','todo']。その後、子コンポーネント内で名前を介してそれらを参照できます。
7. データを親コンポーネントに送信する方法#
React の実装方法#
まず、関数を子コンポーネントに渡します。これは、子コンポーネントを呼び出すときにそれを prop として参照することで行います。その後、this.props.whateverTheFunctionIsCalled を参照して、子コンポーネントに関数を追加します。たとえば onClick などです。これにより、親コンポーネント内の関数がトリガーされます。タスク削除のセクションでこのプロセス全体を詳しく説明しました。
Vue の実装方法#
子コンポーネント内では、値を親関数に送信するための関数を作成するだけです。親コンポーネント内で、子コンポーネントがその値のイベントを発火させるときにそのイベントをリッスンする関数を作成し、イベントをリッスンした後に関数を呼び出します。同様に、タスク削除のセクションでこのプロセス全体を詳しく説明しました。
8. まとめ#
私たちは、データの追加、削除、変更、親コンポーネントから子コンポーネントへのデータの渡し方、そしてイベントリスナーの形式で子コンポーネントから親コンポーネントへのデータの送信方法を研究しました。もちろん、React と Vue の間にはいくつかの小さな違いがありますが、この記事の内容がこの二つのフレームワークを理解するのに役立つことを願っています。
二つのアプリケーションの GitHub アドレス:
**Vue ToDo:**https://github.com/sunil-sandhu/vue-todo
**React ToDo:**https://github.com/sunil-sandhu/react-todo