• vue、react对比


    一、父子通信

    1. 父组件通过props向子组件传值

    vue:
    父组件

    <blog-post :title="My journey with Vue"></blog-post>
    

    子组件接收

    Vue.component('blog-post', {
      props: {
        title: {
          type: String,
          default: ''
        }
      },
      template: '<h3>{{ title }}</h3>'
    })
    

    react:
    父组件:

    <StrategyTable
      maxLength={2}
      styleName="strategy-able"
      onRowClick={this.onRowClick}
      delayTime={500}
      isRefresh={false}
     />
    

    子组件:

    import PropTypes from 'prop-types';
    
      static propTypes = {
        maxLength: PropTypes.number,
        onRowClick: PropTypes.func,
        delayTime: PropTypes.number,
        isRefresh: PropTypes.bool,
      }
      static defaultProps = {
        maxLength: -1,
        onRowClick: () => {},
        delayTime: 0,
        isRefresh: true,
      }
    
      constructor(props) {
        super(props);
        this.state = {
          maxLength: this.props.maxLength // 子组件通过 this.props.属性名 来获取父组件传来的参数
        };
      }
    

    2. 子组件向父组件传参

    vue:
    子组件

    <button @click="toParent">
    Enlarge text
    </button>
    
    methods: {
        toParent() {
          this.$emit('enlarge-text', '我是传过来的值')
        }
    }
    

    父组件

    <blog-post
    ...
    @enlarge-text="changeTxt"
    ></blog-post>
    
    methods: {
        changeTxt(val) {
          //do something
          console.log(val);
        }
    }
    

    react:利用回调函数参数获取子组件传来的值。
    父组件:

    import React, { Component } from 'react';
    
    export default class ListWrap extends Component {
    
    getSunData = (val) => {
      this.text = val;
    }
    
      render() {
         return (
           <div>
            <sunComponent onRowClick={this.getSunData}/>
          </div>
        );
      }
    }
    

    子组件:

    import React, { Component } from 'react';
    import PropTypes from 'prop-types';
    
    export default class sunComponent extends Component {
    
      static propTypes = {
        onRowClick: PropTypes.func,
      }
      static defaultProps = {
        onRowClick: () => {},
      }
    
    toParentEvt() {
      this.props.onRowClick('子组件信息')
    }
    
      render() {
         return (
           <div>
            <ul>
              <li onClick={this.toParentEvt}>我是子组件信息</li>
            </ul>
          </div>
        );
      }
    }
    

    3. 父组件访问子组件属性

    vue:
    父组件

    <recodeList ref="recordChild"></recodeList>
    
    this.$refs.recordChild.属性
    this.$refs.recordChild.方法
    

    react:
    父组件:

    import React, { Component } from 'react';
    
    export default class ListWrap extends Component {
    
    getChild= (ref) => {
      this.childRef = ref;
    }
    
      render() {
         return (
           <div getChildRef={this.getChild}>
            <sunComponent />
          </div>
        );
      }
    }
    

    子组件:

    import React, { Component } from 'react';
    import PropTypes from 'prop-types';
    
    export default class sunComponent extends Component {
    
      static propTypes = {
        getChildRef: PropTypes.func,
      }
      static defaultProps = {
        getChildRef: () => {},
      }
    
    componentDidMount() {
       this.props.getChildRef(this)
    }
    

    4. react使用context实现跨级组件传值

    context是一个全局变量,像是一个大容器,在任何地方都可以访问到,我们可以把要通信的信息放在context上,然后在其他组件中可以随意取到;
    但是React官方不建议使用大量context,尽管他可以减少逐层传递,但是当组件结构复杂的时候,我们并不知道context是从哪里传过来的;而且context是一个全局变量,全局变量正是导致应用走向混乱的罪魁祸首.

    对于父组件,也就是Context生产者,需要通过一个静态属性childContextTypes声明提供给子组件的Context对象的属性,并实现一个实例getChildContext方法,返回一个代表Context的纯对象 (plain object) 。

    import React from 'react'
    import PropTypes from 'prop-types'
    
    class MiddleComponent extends React.Component {
      render () {
        return <ChildComponent />
      }
    }
    
    class ParentComponent extends React.Component {
      // 声明Context对象属性
      static childContextTypes = {
        propA: PropTypes.string,
        methodA: PropTypes.func
      }
      
      // 返回Context对象,方法名是约定好的
      getChildContext () {
        return {
          propA: 'propA',
          methodA: () => 'methodA'
        }
      }
      
      render () {
        return <MiddleComponent />
      }
    }
    

    而对于Context的消费者,通过如下方式访问父组件提供的Context。

    import React from 'react'
    import PropTypes from 'prop-types'
    
    class ChildComponent extends React.Component {
      // 声明需要使用的Context属性
      static contextTypes = {
        propA: PropTypes.string,
      }
      
      render () {
        const {
          propA,
          methodA
        } = this.context
        
        console.log(`context.propA = ${propA}`)  // context.propA = propA
        console.log(`context.methodA = ${methodA}`)  // context.methodA = undefined
        
        return ...
      }
    }
    

    子组件需要通过一个静态属性contextTypes声明后,才能访问父组件Context对象的属性,否则,即使属性名没写错,拿到的对象也是undefined。

    几个可以直接获取Context的地方:
    实际上,除了实例的context属性(this.context),React组件还有很多个地方可以直接访问父组件提供的Context。比如构造方法:
    constructor(props, context)

    比如生命周期:
    componentWillReceiveProps(nextProps, nextContext)
    shouldComponentUpdate(nextProps, nextState, nextContext)
    componetWillUpdate(nextProps, nextState, nextContext)

    二、生命周期

    vue:
    1. beforeCreate
    在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
    2. created
    在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前尚不可用。
    3. beforeMount
    在挂载开始之前被调用
    4. mounted
    实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。
    5. beforeUpdate
    数据更新时调用,发生在虚拟 DOM 打补丁之前。
    6. updated
    数据更新后调用,发生在虚拟 DOM 打补丁之后。在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
    注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick

    updated: function () {
      this.$nextTick(function () {
        // Code that will run only after the
        // entire view has been re-rendered
      })
    }
    

    7. activated
    被 keep-alive 缓存的组件激活时调用
    8. deactivated
    被 keep-alive 缓存的组件停用时调用
    9. beforeDestroy
    实例销毁之前调用。在这一步,实例仍然完全可用。
    10. destroyed
    实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
    11. errorCaptured (2.5.0+ 新增)
    类型:(err: Error, vm: Component, info: string) => ?boolean
    当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

    image.png

    beforeRouteEnter(to, from, next):进入路由之前执行的函数
    beforeRouteLeave(to, from, next):离开路由之前执行的函数

    react:
    组件的生命周期可分成三个状态:

    • Mounting:已插入真实 DOM
    • Updating:正在被重新渲染
    • Unmounting:已移出真实 DOM

    生命周期的方法有:

    • componentWillMount: 在渲染前调用,在客户端也在服务端。
    • componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
    • componentWillReceiveProps: 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
    • shouldComponentUpdate : 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
      可以在你确认不需要更新组件时使用。
    • componentWillUpdate: 在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
    • componentDidUpdate: 在组件完成更新后立即调用。在初始化时不会被调用。
    • componentWillUnmount: 在组件从 DOM 中移除之前立刻被调用。
      image.png

    三、路由

    Vue:
    路由模式: history、hash(默认)
    路由跳转:

    <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
    <router-link :to="{ path: '/abc'}" replace></router-link>
    router.push(location, onComplete?, onAbort?)
    router.push(location).then(onComplete).catch(onAbort)
    router.replace(location, onComplete?, onAbort?)
    router.replace(location).then(onComplete).catch(onAbort)
    router.go(n)
    router.back()
    router.forward()
    

    参数:
    { name: xxx, params: {...}, query: {..} }或者{ path: xxx, query: {..} }
    获取参数:this.$route.paramsthis.$route.query

    生命周期:

    router.beforeEach((to, from, next) => {
      /* 必须调用 `next` */
    })
    
    router.beforeResolve((to, from, next) => {
      /* 必须调用 `next` */
    })
    
    router.afterEach((to, from) => {})
    

    react:
    路由模式: browserHistory、hashHistory、createMemoryHistory

    路由跳转:

    <Link to={`/users/${user.id}`} activeClassName="active">{user.name}</Link>
    this.props.history.push({...})
    this.props.history.replace({...})
    this.props.history.go(n)
    this.props.history.goBack()
    this.props.history.goForward()
    

    参数:
    { pathname: xxx, query: {..}, state: {...} }
    获取参数:props.location.queryprops.location.state

    生命周期:
    routerWillLeave(nextLocation)

  • 相关阅读:
    分布式搜索引擎Elasticsearch的查询与过滤
    剖析Elasticsearch集群系列第一篇 Elasticsearch的存储模型和读写操作
    分布式缓存 cachecloud
    npm是什么NPM的全称是Node Package Manager
    Grafana监控可视化环境搭建
    github ssl验证跳过
    Linux分区扩容
    手把手教你把Vim改装成一个IDE编程环境(图文)
    根据条件批量删除document
    奇智网络聊天机器人
  • 原文地址:https://www.cnblogs.com/SPHmomo/p/12935732.html
Copyright © 2020-2023  润新知