React和Vue特性和書寫差異


Vue均使用ES6語法,主要以單文件組件為例,寫法上優先使用縮寫。

React使用TS語法。

生命周期

  • Vue

vue-lifecyle

  • React

react-lifecyle

入口&根實例

  • Vue
const app = new Vue({ /* 選項 */ render: (h) => h(App) // App為根組件 }).$mount('#app')
  • React
ReactDOM.render( <App/>, // App為根組件 document.getElementById('app') )

組件定義

  • Vue
// 定義組件構造器 var MyComponent = Vue.extend({/* 選項 */}) // 注冊全局組件 Vue.component('my-component', {/* 選項 */})
<!-- 單文件組件 --> <template> <div class="my-component">hello</div> </template> <script>  export default {  /* 選項 */  } </script>
  • React
// 無狀態組件 const Foo = () => { return <div className='foo'></div> }
// 完整組件 class Foo extends React.Component<{}, void> { render () { return <div className='foo'>hello</div> } }

組件引用

  • Vue
<!-- 以單文件組件為例:Foo.js --> <template> <div class="Foo"> <!-- 必須小寫,不能自閉合 --> <bar></bar> </div> </template> <script>  // 引入組件  import Bar from './Bar'   export default {  name: 'Foo',  components: {Bar}  } </script>
  • React
import Bar from './Bar' class Foo extends React.Component<{}, void> { render () { return ( <div className='foo'> {/* 組件約定大寫開頭,可自閉合 */} <Bar/> </div> ) } }

組件內部狀態

  • Vue
<template>
  <div class="foo"> <p class='name'>{{name}}</p> <p class='age'> {{age}} <button @click="onAdd">add</button> </p> </div> </template> <script>  export default {  data () {  return {  name: 'Tom',  age: 18  }  },  methods {  onAdd () {  // 直接修改  this.age++  }  }  } </script>
  • React
interface IFooState {
  name: string, age: number } class Foo extends React.Component<{}, IFooState> { state = { name: 'tom', age: 18 } onAdd = () => { // 必須通過setState修改 this.setState({ age: this.state.age + 1 }) } render () { const {name, age} = this.state return ( <div className='foo'> <p class='name'>{name}</p> <p class='age'> {age} <button onClick={this.onAdd}>add</button> </p> </div> ) } }

父子組件通訊

  • Vue
<!-- Parent.vue --> <template> <div class="parent"> <child name='tom' :age='18' @click="onAdd"></child> </div> </template> <script>  export default {  data () {  return {  age: 18  }  },  methods {  onAdd () {  this.age++  }  }  } </script>
<!-- Child.vue --> <template> <div class="child"> <p class='name'>{{name}}</p> <p class='age'> {{age}} <button @click="onAdd">add</button> </p> </div> </template> <script>  export default {  props: {  name: {type: String},  age: {type: Number, default: 18}  },  methods {  onAdd () {  this.$emit('click')  }  }  } </script>
  • React
interface IChildProps {
  name: string, age?: number, onAdd?: () => void } class Child extends React.Component<IChildProps, void> { static defaultProps = { age = 18, onAdd: () => {} } render () { const {name, age} = this.props return ( <div className='child'> <p class='name'>{name}</p> <p class='age'> {age} <button onClick={this.onAdd}>add</button> </p> </div> ) } } interface IParentState { age: number } class Parent extends React.Component<{}, IParentState> { state = { age: 18 } onAdd = () => { this.setState({ age: this.state.age + 1 }) } render () { const {name, age} = this.state return ( <div className='parent'> <Child name='Tom' age={18} onAdd={this.onAdd}></Child> </div> ) } }

模板/JSX語法

  • Vue
<!-- 可搭配其他模板語言,如Pug等 --> <template> <!-- 變量 --> <div>{{name}}</div> <!-- 表達式 --> <div>{{ ok ? 'YES' : 'NO' }}</div> <!-- HTML --> <div v-html="rawHtml"></div> <!-- 屬性:屬性名必須小寫(kebab-case) --> <div id="app"></div> <div :id="dynamicId"></div> <foo :task-count="18"></foo> <foo :class="['item', foo]"></foo> <foo :style="{'margin-top': '10px'}"></foo> <!-- 事件 --> <foo @action="onAction"></foo> </template>
  • React
render () {
  return ( <!-- 變量 --> <div>{name}</div> <!-- 表達式 --> <div>{ ok ? 'YES' : 'NO' }</div> <!-- HTML --> <div dangerouslySetInnerHTML={rawHtml}></div> <!-- 屬性 --> <div id='app'></div> <div id={dynamicId}></div> <foo taskCount={18}></foo> <foo className={'item ' + foo}></foo> <foo style={{marginTop: 10}}></foo> <!-- 事件 --> <foo onAction="onAction"></foo> ) }

條件渲染

  • Vue
<template>
  <div v-if="foo">foo</div> </template> <template> <div v-if="foo">foo</div> <div v-else-if="bar">bar</div> </template> <template> <div v-if="foo">foo</div> <div v-else-if="bar">bar</div> <div v-else>other</div> </template>
  • React
render () {
  return foo && <div>foo</div> } render () { return foo ? <div>foo</div> : <div>bar</div> } render () { return ( { foo ? <div>foo</div> : bar ? <div>bar</div> : <div>other</div> } ) }

列表渲染

  • Vue
<template>
  <div class='list'> <div v-for="item in list" :key="item">{{item}}</div> </div> </template>
  • React
render () {
  return ( <div className='list'> {list.map((item) => <div key={item}>{item}</div>)} </div> ) }
// 或者 render () { const items = list.map((item) => <div key={item}>{item}</div>) return ( <div className='list'> {items} </div> ) }

表單&雙向綁定

  • Vue
<!-- 表單 --> <template> <form> <input v-model="name"> <!--  相當於以下的語法糖:  <input v-bind:value="name" v-on:input="name = $event.target.value">  在組件中相當於  <foo v-bind:value="name" v-on:input="name = arguments[0]"></foo>  --> </form> </template> <script>  export default {  data () {  return {  name: ''  }  }  } </script>
<!-- Vue 2.3.0+ --> <!-- Parent.vue --> <template> <child :foo.sync="bar"></child> <!--  sync只是語法糖,實際上拓展為:  <child :foo="bar" @update:foo="val => bar = val"></child>  --> </template> <!-- Child.vue --> <script>  export default {  methods: {  onChange () {  this.$emit('update:foo', newValue)  }  }  } </script>
  • React
interface IFooState {
  name: string } class Foo extends React.Component<{}, IFooState> { onChange = (e) => { const name = e.target.value this.setState({name}) } render () { const {value} = this.state return ( <div> <input value={value} onChange={this.onChange}/> </div> ) } }

內容分發

  • Vue
<!-- Child --> <template> <!-- 必須有根元素 --> <div class="child"> <slot name="header"></slot> <slot></slot> <slot name="footer"></slot> </div> </template> <script>  export default {} </script> <!-- Parent --> <template> <div class="parent"> <child> <p slot="header">header</p> <p>content</p> <p slot="footer">footer</p> </child> </div> </template> <script>  import Child from './Child'  export default {  components: {Child}  } </script>
  • React
interface IChildProps {
  header?: React.Node, children?: React.Node, footer?: React.Node } class Child extends React.Component<IChildProps, void> { render () { const {header, children, footer} = this.props return ( <div className='child'> {header} {children} {footer} </div> ) } } class Parent extends React.Component<{}, void> { render () { return ( <div className='parent'> <Child className='child' header='header'} footer={<p>footer</p>}> <p>content</p> </Child> </div> ) } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM