• 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>
        )
      }
    }
  • 相关阅读:
    热爱工作 发财机会大增(这里不是选择软件还是硬件的问题,是自己的性格和追求的问题)——当你的老板不如你懂行的时候,还赚的盆满钵满的时候,你就可以考虑独立了 good
    TaintDroid:智能手机监控实时隐私信息流跟踪系统(三)
    Delphi读取文件属性
    创业者该如何看待腾讯的“跟进”?
    IBM总裁郭士纳总结的四类人
    迅雷程浩:企业外包服务,下一个大的风口?(2B业务一定要懂销售和营销的人,这点和2C 不一样)
    dddd
    android:minSdkVersion 之我见
    dddd
    请人不怕啦
  • 原文地址:https://www.cnblogs.com/libin-1/p/6891714.html
Copyright © 2020-2023  润新知