关于react与vue的一些对比(上)

一、背景

Vue

        Google前端工程师尤雨溪于2014年创建了这个框架,Vue是一套用于构建用户界面的渐进式框架,与其他大型框架不同的是,Vue被设计为可以自底向上逐层应用,Vue核心时只关注视图层,不仅易于上手,还便于与第三方库或既有的项目整合

React

        与Vue不同,react库是由FaceBook创建的,最初是为了FackBook广告流量管理创建的,那是FackBook遇到了维护和编码方面的问题,它以动态创建和交互UI的能力而闻名

二、核心思想

        vue和react都是推崇组件式的开发理念,但是在设计的核心思想上有很大的差别

Vue

        Vue的整理思想仍然是拥抱经典的html(结构)+css(表现)+jd(行为)的形式,Vur鼓励开发者使用template模板,并提供指令供开发着使用(v-if、v-show、v-for等等),因此开发vue应用又是会有一种在写经典web应用(结构、表现、行为分离)的感觉。另一方面,在针对组件数据上,Vue2.0通过Object.defineProperty对数据做到了更细致的监听,景区实现组件级别的更新。

React

        react整体上是函数式的思想,组件使用jsx语法,all in js,将html与css全部融入javaScript,jsx语法相对来说更加灵活,刚开始从Vue转React的时候我也不是很适应,觉得react的写法很自由。当组件调用setState或props变化的时候,组件内部render会重新渲染,子组件也会随之重新渲染,可以通过shouldComponentUpdate或者PrueComponent可以避免不必要的重新渲染

三、组件形式

Vue

        vue组件是使用.vue文件来表示,vue组件将html、css、js组合到一起,模板部分使用数据使用{{}},形式如下:

// 模板(html)


// 数据管理(js)


// 样式(css)

组件的使用:

react

        react推荐使用jsx或者js文件来表示组件,react支持class组件和function组件,react中是使用{}包裹变量,且需要注意的是,组件名称必须大写字母开头,React会将以小写字母开头的组件视为原生Dom标签,例如

代表html的div标签,而则代表一个组件,并且需在作用域使用Welcome

1)class组件

import React from 'react';

class NewComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'xx'
    };
  }
  render() {
    rerurn(
{name}
); } } export default NewComponent;

2)function组件

import React, { useState } from 'react';

function NewComponent() {
  const [name, setName] = useState('');
  return (
{name}
); } export default NewComponent;

四、数据管理(props、data、state)

组件中数据管理通常包含2部分,来自父组件的数据props与自身的数据

vue与react中的props都是单项数据流的,父级prop的更新会向下流动到子组件中,但是反过来不行。props可以是数组或对象,用于接收来自父组件的数据。

Vue

Props

vue中的的props支持传递静态或者动态props,静态props一般传递字符串

静态prop传递布尔值true可以这样写,传值false仍然需要使用动态prop传值

动态赋值使用v-bind,可以简写为:


// 简写形式

动态prop常用来传递对象、数组、布尔值(false值,true值可以直接传属性 )等

data

vue中使用data来管理组件的数据,vue将会递归将data数据转为getter/setter,从而让data的属性能够响应数据变化。对象必须是纯粹的对象(含有零个或多个key/value对)。一旦观察过,不需要再次在数据对象上添加响应式属性。因此推荐在创建实力之前,就声明所有的根级响应式属性。

当一个组件被定义,data必须声明为返回一个初始数据对象的函数

export default {
  name: 'NewComponent',
  data() {
    return {
      name: 'xxx',
      age: 12
    }
  }
}

当需要在组件内修改数据时,可以直接通过vue实力来修改:

  methods: {
    changeName() {
      this.name = 'new Name';
    }
  }

React

props

react中的props也与vue一样可以传递静态或动态props,静态props一般传递字符串

函数组件和class组件都可以使用props,函数组件使用props参数获取父组件传递的props

1)函数组件获取props

function Welcome(props) {
  return 

Hello, {props.name}

; } const element = ;

2)class组件获取props(通过this.props获取)

class Welcome extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    const { name } = this.props;
    return 
{name}
; } }

动态的props

state

react中使用state来管理组件内的数据,hooks的出现使用函数组件也具备管理state的能力

1)class组件中的state

class组件在构造函数(constructor)中定义组件内数据(state),修改数据必须通过setSate修改,不能直接修改state,这点非常重要。

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'xx'
    };
    this.changeName = this.changeName.bind(this);
  }

  changeName() {
    this.setState({
      name: 'new name'
    });
  }

  render() {
    const { name } = this.state;
    return 
{name}
; } }

关于class组件的setState有以下需要注意点:

  • setState更新是异步的,但是在setTimeout和原生时间中式同步的

  • setState更新式组件部分数据,更新机制式合并数据

  • 当需要使用上一个state值时,可以让setSate()接收一个函数而不是一个对象。这个函数用上一个state作为第一个参数,将此次更新被应用时的props作为第二个参数:

this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

2)function组件中的useState(hook)

react16.0之前函数组件知识纯的渲染组件,hooks的出现赋予了函数组件管理state的能力

useState返回一个state,以及更新state的函数,如果新的state需要通过使用先前的state计算得出,那么可以将函数传递给setState。该函数将接收先前的state,并返回一个更新后的值

import React, { useState } from 'react';

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      
      
      
    
  );
}

关于setState有一下注意点:

  • 与class组件中的setState方法不同,useState不会自动合并更新对象
  • 只能在函数最外层调用Hook,不要再循环、条件判断中胡总子函数中调用
  • 只能再React的函数组件或者自定义hook中调用hook,不要在其他JavaScript函数中调用

五、组件数据交互

组件数据交互指的是父子组件、兄弟组件、跨层组件之间传递数据。兄弟组件之间可以通过事件总线或者通过父组组件传递数据

1.父子组件数据交互(props+自定义事件 VS props+回调)

vue:props+自定义事件

react:props+回调

Vue

vue中父组件通过props传递数据给子组件,子组件使用$emit触发自定义事件,父组件中监听子组件的自定义事件获取子组件传递过来的数据

子组件中使用$emit传递自定义事件myEvent



父组件使用@myEvent监听自定义事件,回调参数是子组件传回的数据:



React

react中父组件使用props传递数据和回到函数给子组件,子组件通过props传下来的回调和桉树返回数据,父组件通过回调函数获取子组件传递上来的数据

子组件通过props接收夫罪案传下来的回调事件:

import React, { useState } from 'react';

function Children(props) {
  const { myEvent } = props;
  const [name, setName] = useState('xxx');

  const changeName = () => {
    setName('new name');
    myEvent('new name');
  };
  return 
{name}
; }

父组件通过回到事件获取子组件传递的参数:

function Parent() {
  const changeName = name => {
    console.log(name);
  };
  return ;
}

2.跨组件数据交互(provide/inject VS Context)

vue和react都支持跨组件传递数据,vue中主要通provide/inject实现,react中主要是通过Context实现

Vue

vue中通过provide/inject在祖先组件向所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效

祖先组件中定义provide选项,provide选项应该是一个对象或者返回一个对象的函数



子组件通过inject选项获取祖先组件provide选项值,inject选项应该是一个字符串数组或者对象



注意:provide和inject绑定并不是可响应式的,这是刻意为之,然而,如果你传入一个可监听的对象,那么其对象的属性还是可响应的。

react

Context提供了一个无需为每层手动添加props,就能在组件树间进行数据传递的方法

import React,{useState} from 'react'

//创建Context对象
const MyContext=React.createContect({theme:'black'})
function Parent(){
    const changeName=name=>{
        console.log(name);
    }
    //Context.provider向消费组件传值
    return (
        
            
        
    )
}

消费组件获取Context的两种方式:

1)class组件通contextType获取最近Context上的那个值

class DeepChildren1 extends React.Component{
    constructor(props){
        super(props)
    }
    
    static contextType=MyContext;

    render(){
        return (
            
{this.context.theme}123
) } }

2)函数组件通过Context.Consumer订阅到Context的变更

function DeepChildren(props){
    return (
        
            {
                (value)=> (
{value.theme}
) }
) }

关于Context需要注意:

  • 当Provider的父组件进行重新渲染时,consumers组件会重新渲染,并且没有办法避免,应该尽量避免使用Context

六、class与style

对于css中class与style处理上,vue与react也存在较大差异

Vue

vue对class与style特意做了增强,可以传字符串、对象、数组

class

1)给class绑定字符串

2)给class绑定对象

data如下:

data: {
  isActive: true,
  hasError: false
}

HTML将被渲染成:

3)给class绑定数组

data如下:

data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

 HTML 将被渲染为:

style

style用来绑定内联样式,支持传对象、数组、使用需要添加浏览器引擎的css属性时,如transform、Vue.js会自动侦测并添加相应的前缀

1)传对象,css属性名可以用驼峰式或者短横线分割

data如下:

data: {
  activeColor: 'red',
  fontSize: 20
}

HTML将被渲染为:

2)传数组将多个样式应用到同一个元素上:

data如下:

baseStyles: {
  fontSize: '20px',
  color: 'blue'
},
overridingStyles: {
  height: '80px'
}

HTML将被渲染为:

react

react使用className用于指定css的class,react不能直接为组件指定class

className

react中的饿className一般传值字符串常量或者字符串变量,不能传递数组或者对象语法

1)传递字符串常量

function NewComponent(){
    return 
this is a new Component.
}

2)传递字符串变量

function NewComponent(){
    const newClass='container'
    return 
this is a new Component.
}

3)传递多个class,可以使用es6的模板字符串实现

function NewComponent(){
    const newClass="container"
    return 
.....
}

4)如果需要传递数组或者对象语法时,可以引入classnames库实现:

import classNames from 'classnnames';

function NewComponent() {
  const newClass = 'container';
  return 
This is New Component.
; }

html将被渲染为:

This is New Component.

style

通常不推荐将style属性作为设置元素样式的主要方式。在多数情况下,应使用className属性来引用外部css样式表中定义的class。style在react应用中多用于在渲染过程中添加动态计算样式

const divStyle={
    color:'blue',
    backgroundImage:'url('+imgUrl+')'
}

function HelloWordComponent(){
    return 
Hello World!
}

注意:样式不会自动补齐前缀,如需支持旧版本浏览器,请手动补充对应对的样式属性:

const divStyle = {
  WebkitTransition: 'all', // note the capital 'W' here
  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};

function ComponentWithTransition() {
  return 
This should work cross-browser
; }

七、生命周期

我们经常说的生命周期无谓就是组件的生命周期,一般包括:初始化,挂在、更新、卸载四个大阶段,接下来分别看看vue和react的生命周期

Vue

vue生命周期图示:

关于react与vue的一些对比(上)_第1张图片

 React

react生命周期氛围16.0之前和16.0之后

16.0之前

关于react与vue的一些对比(上)_第2张图片

 1)初始化阶段:constructor

        是class组件默认的方法,常用来初始化state或者设置属性等

class Counter extends React.component{
    construtor(props){
        super(props)
        this.state={
            count:0
        }
        this.color='red'
    }

}

2)挂在阶段

  • componentWillMount():组件挂在之前调用,并且只会调用一次
  • render:render是React组件必须定义的生命周期函数,用来渲染DOM。 并必须返回一个React元素(描述组件,即UI),不负责组件实际渲染工作,之后由React自身根据此元素去渲染出页面DOM

注意:不要在render里面修改state,会引起死循环导致卡死

  • componentDidMount():组件挂载完毕之后调用,在这个阶段可以获取真实Dom元素,宠用来发起异步请求获取数据

3)更新阶段:

但通过setState修改state或父组件重新render引起props更新,都会引起子组件的重新render

  • componentWillReceiveProps(nextProps):props发生变化以及父组件重新渲染时都会触发该生命周期函数。在该阶段可以通过参数nextProps获取变化后的props参数,通过this.props访问之前的props,该生命周期内可以进行setState
  • shouldComponentUpdate(nextProps,nextState):组件每次setState或者父组件chongxinrender都会引起子组件render,可以使用该钩子比较nextProps,nextState以及当前组件的this.props,this.state的状态来判断是否需要重新渲染。默认返回true(会重新渲染);返回false则不触发渲染。

一般我们通过该钩子来优化性能,避免子组件不必要的渲染

  • componentWillUpdate(nextProps,nextState):当组件收到新的props或者state时,就会渲染之前调用,使用此作为更新发生之前执行准备更新的机会。初始渲染不会调用该方法 

注意:不能在此方法中调用this.setState

  • componentDidUpdate(prevProps,prevState):此方法在组件更新后被调用。首次渲染不会执行才方法,当组件更新后,可以在此处对DOM进行操作

注意:可以在componentDidUpdate()中直接调用setState(),但是它必须被包裹在一个条件语句中,否则会导致死循环

 4)卸载阶段

  • componentWillUnmount():会在组件卸载及销毁之前直接调用,在此方法中执行必要的清理操作,例如:清除timer,取消网络请求或清除在componentDidMount()中创建的订阅等

注意:componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。

 16.0之后

react16.0之后移除的生命周期函数:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

但是为了向下兼容,react并未删除这三个生命周期函数,新增“UNSAFE_”为前缀别名和的三个函数:UNSAFE_componentWillMount()UNSAFE_componentWillReceiveProps()UNSAFE_componentWillUpdate()

新增的生命周期函数

  • static getDerivedStateFromProps(nextProps,preState)
  • getSnapshotBeforUpdate(nextProps,prevState)

react16.0更新之后的生命周期函数总结:

(1)初始化阶段保持不变

(2)挂载阶段:getDerivedStateFromProps=>render=>componentDidMount

(3)更新阶段:getDerivedStateFromProps=>shouldComponentUpdate=>render=>getSnapshotBeforeUpdate=>componentDidUpdate

(4)卸载阶段保持不变

八、事件处理

vue和react在事件处理上用法也有所差异

Vue

vue中使用的是v-on指令的方式为元素绑定时间,并在出发时运行一些JavaScipt代码,通常使v-on接受一个需要调用的方法名称

1)直接绑定方法,不传递任何参数,回调函数参数是浏览器事件event对象

Greet

method:

  methods: {
    greet(event) {
      console.log(event);
    }
  }

2)内联调用方法

Greet
methods: {
  greet(message) {
    this.message = message;
  }
}

有时候也需要在method中访问原生DOM事件,可以讲$event显示传入method中

Greet
methods: {
  greet(message, event) {
    this.message = message;
  }
}

3)事件修饰符和按键修饰符

Vue为事件添加了事件修饰和按键修饰符

事件修饰符:

在事件处理程序中调用event.preventDefault()或者event.stopPropagation()是非常常见的需求,为了解决这个问题,Vue为v-on提供了事件修饰符,修饰符是由.开头的指令后缀来表示的。

  • .stop:阻止事件继续传播
  • .prevent:阻止事件默认行为
  • .self:当前元素触发时才触发时间处理函数
  • .once:事件只触发一次
  • .passive:告诉浏览器你不想阻止事件默认行为,不能和prevent一起使用




...
...

你可能感兴趣的:(react.js,javascript,vue.js)