react的作用好处_站在vue的角度看react

b775e922a6b2f1837327e155dfe89ca6.png

作为一个用vue撸了3年多代码的切图仔,最近在使用的react重构一个项目;写惯了vue之后再来写react,会发现两者有大的不同,但是仔细品味一下又会发现,其实两者很像。本文就从vue出发,结合这段时间的开发体验,感性地对比下二者在使用上的异同;注:本文讨论的是vue2.x的版本和react16.13.x版,函数式编程。

模板 template

vue 使用的是接近于 html 的模板语法;

<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>

export default {
  name: 'App',
  data() {
    return {
      msg: 'hello-vue'
    }
  }
}
</script>

<style>
</style>

react使用的 jsx 语法,这个语法更像是把 html 标签嵌入到 js 内,函数组件需要返回一个 jsx;

function App() {
  const name = 'hello react'
  return (
    <div className="App">
      {name}
    </div>
  );
}

export default App;

注意

  1. vue 和 react 的模板语法实际上都是“语法糖”,他们都需要通过编译,生成相应的 render 函数,最终渲染成真实的 dom 元素
  2. vue 的思路是拥抱前端"三板斧": html、js、css 分开(vue同时也支持 jsx );而 react 拥抱 js,希望把所有的东西都交给 js 去实现;
  3. vue 的文本插值是“Mustache”语法 (双大括号),而 react 是花括号包裹即可,都支持嵌入表达式;vue 支持在双大括号内输出对象、布尔值等,而 react 只能输出文字和数字;
  4. 样式上,vue 写样式直接就是 class,而 react 支持类的写法,class 关键字被占用,所以使用的是 className ;vue 的单组件文件支持局部样式表,只需要在 style 标签加 scoped 属性即可,而 react 支持局部变量需要用到 cssModule,把样式当成模块引入,且类名不支持通用的 BEM(可以用驼峰和下划线的方式,强迫症表示很难受);

数据 data

vue 的数据都是挂载在当前实例下的(包括props、data、method、computed等,这也是为什么在单组件文件下通过 this 可以访问到这些属性),声明时要分别定义;data 声明后即是响应式的,改变数据会同步反映到视图上;

<template>
  <div>
    {{ msg }}
        {{ name }}
    {{ computedName }}
  </div>
</template>

<script>

export default {
  name: 'App',
    props: ['name'],
  data() {
    return {
      msg: 'hello-vue'
    }
  },
  computed: {
    computedName() {
      return `${this.name} computed`;
    },
  }
}
</script>

react 的函数组件的数据都是放在函数内部声明,每次渲染的时候都会执行一次;响应式数据需要利用 hook — useState 主动触发;

import React, { useState } from 'react';

function App({ name }) {
  const [state, setstate] = useState('state');

  return (
    <div className="App">
      {name}
      {state}
      <button onClick={() => {
        setstate('state change');
      }}>
        click me
      </button>
    </div>
  );
}

export default App;

注意

  1. vue 和 react 都是数据驱动视图的框架,提倡开发者专注数据层逻辑的开发,通过数据变更驱动视图更新;
  2. vue 在数据声明时就已经做了响应式的处理,而 react 则需要使用 useState 手动触发视图更新。使用下来感觉 vue 的好处是可以直接处理数据,数据是怎么样的,视图就是怎么样的,使用起来很方便;react 需要处理完数据后主动调用 useState ,这样的好处是你永远知道触发视图更新的操作在哪里,而 vue 虽然使用方便,但是也容易出现不符合预期的表现。

侦听器 watcher

vue 提供 watch 属性,用于当数据依赖发生变化时执行相应的逻辑。

<template>
  <div>
    {{ msg }}
    <input type="text" v-model='msg'>
  </div>
</template>

<script>

export default {
  name: 'App',
  data() {
    return {
      msg: ''
    }
  },
  watch: {
    msg() {
      // ...
    }
  }
}
</script>

react 使用处理副作用的 hook — useEffect;

import React, { useState, useEffect } from 'react';

function App() {
  const [state, setstate] = useState('state');

  useEffect(() => {
    // ...
  }, [state])

  return (
    <div className="App">
      {state}
      <button onClick={() => {
        setstate('state change');
      }}>
        click me
      </button>
    </div>
  );
}

export default App;

注意

  1. vue 的 watch 属性只能订阅一个数据源,而 react useEffect 的 hook,可以指定多个依赖;
  2. useEffect 会在首次渲染的时候执行一次,watch 也支持,不过需要指定 immediate 的 config;如果 useEffect 想在首次渲染时不执行,可以利用 useRef 在组件的整个周期的不变性进行条件控制;

计算属性 computed

vue 提供 computed 属性进行动态求值,每次内部依赖的数据发生变化,计算属性就会重新计算;计算属性的好处是可以减少在模板写过多的逻辑和缓存计算结果(不是每次渲染都重新计算一次,而是依赖变化了才进行计算)

<template>
  <div>
    {{ msg }}
    {{ computedData }}
    <input type="text" v-model="msg">
  </div>
</template>

<script>

export default {
  name: 'App',
  data() {
    return {
      msg: ''
    }
  },
  computed: {
    computedData() {
      return this.msg + this.msg;
    }
  }
}
</script>

react 可以使用变量声明的方式实现相同的效果,这个操作和 vue 直接在 template 写表达式是一样的,缺点是每次渲染都会执行;如果考虑性能的话,则可以使用 hook — useMemo,并指定依赖项;这样就可以实现 vue computed 一样的效果了。

import React, { useState, useEffect, useMemo } from 'react';

function App() {
  const [state, setstate] = useState('state');

    // 每次渲染都会重新计算
  const computed = `${state}`;
    // 依赖的 state 变化了才会重新计算
  const computedMemo = useMemo(() => {
    return state;
  }, [state]);

  useEffect(() => {
    console.log(state);
  }, [state])

  return (
    <div className="App">
      {state}
      {computed}
      {computedMemo}
      <button onClick={() => {
        setstate('state change');
      }}>
        click me
      </button>
    </div>
  );
}

export default App;

注意

  1. vue 的计算属性的依赖不需要主动指定(编译阶段 vue 内部就帮你关联了),而 react 使用 useMemo 需要主动指定依赖;

事件 event

vue 的事件是通过 v-on 或 @ 的方式进行监听,$emit 的方式进行触发的

<template>
  <div>
        <!-- 监听 button 的点击事件,并 emit 自定义的 clickButton 事件 -->
    <button @click="$emit('clickButton')"></button>
  </div>
****</template>

react 的事件都是通过 props 传入回调实现的

function App({ handleClickButton }) {

  return (
    <div className="App">
      <button onClick={() => {
        handleClickButton();
      }}>
        click me
      </button>
    </div>
  );
}

export default App;

生命周期

vue 有一系列的生命周期函数,如 mounted、created 等

<script>
export default {
  name: 'App',
  created() {
    // ...
  },
  mounted() {
    // ...
  }
}
</script>

react 使用类的写法时也会有各种生命周期函数,如: componentDidMount、componentWillUnmount;但是使用 hook 写 react 组件时没有相应的生命周期函数,但是他提供了 useEffect 的 hook 用于处理副作用;虽然没有一一对应起来,但是我们可以通过一些使用上的技巧实现相应的功能;

function App() {
    // 不添加任何依赖(空数组),只会在 render 时执行一次,类似于 vue 的 created 或者 mounted
  useEffect(() => {
    // ...
  }, []);

    // 在 useEffect 内返回一个函数,实际上这个函数会在组件被卸载的时候执行
    // 结合上一个例子就可以实现 mounted 和 beforeDestroyed 的组合
    // 我们通常会这个组合里 addlistener 和 removelistener
    useEffect(() => {
    // ...
        return () => {
            // ...
        }
  }, []);

    // 依赖数组都去掉了,这个 effect 每次渲染都会执行,类似于 vue 的 updated
    useEffect(() => {
        // ...
    });

  return (
    <div className="App">
    </div>
  );
}

export default App;

插槽 slot

vue 提供了 slot 相关的 api,用于分发不同的内容

<!-- 声明 botton-component.vue-->
<template>
    <button type="submit">
      <slot></slot>
    </button>
</template>

<!-- 使用 -->
<botton-component> slot </botton-component>

react 不显示支持插槽的写法,但是可以通过每个组件自带的 children 属性 或者传入 jsx 属性实现

// children 属性
// 声明
function App({ children }) {
  return (
    <div className="App">
      {children}
    </div>
  );
}

// 使用
// App 组件的 children 属性实际上就对应了 <div>children</div>
<App>
    <div>children</div>
</App>

// jsx 属性
// 声明
function App({ slot }) {
  return (
    <div className="App">
      {slot}
    </div>
  );
}
// 使用
<App slot={<div>children</div>}></App>

指令 directive

vue 提供了一系列非常好用的指令,比如 v-model 、v-if 等,他实际上做的事就是在 dom 不同的钩子回调中执行不同的回调,进而实现相应的功能;react 本身没有提供这个功能,不过指令能实现的功能都可以用其他方式解决;

<h1 v-if="awesome">Vue is awesome!</h1>
  • 条件渲染
// vue
<template>
    <h1 v-if="awesome">Vue is awesome!</h1>
    <h1 v-else>Oh no  </h1>
</template>
// react
function App({ children }) {
  return (
    {
        awesome && <>React is awesome too!</>
    }
    {
        !awesome && <>Oh no  </>
    }
    // 或
    {
        awesome ? <>React is awesome too!</> : <>Oh no  </>
    }
  );
}
  • 列表渲染
// vue
<template>
  <div v-for="item in [1, 2, 3]" :key="item">
    {{ item }}
  </div>
</template>
// react
function App({ children }) {
  return (
    {
        [1, 2, 3].map(item => {
            return <div key={item}>{item}</div>
        })
    }
  );
}

插件

vue 官方提供了一系列的插件供开发者使用;而 react 的库大多都是由社区的开发者提供和维护的;像 vue-router 和 react-router、vuex 和 readux 等;

实际开发体验

react 项目初步做下来,会感觉需要自己思考的事情很多,react 的 api 其实很少,它很灵活,只关注核心能力:比如数据驱动视图、jsx等,其他的全权交给开发者处理。

而 vue 不止提供数据驱动、模板编译等能力,还提供了一系列的“标准”甚至“最佳实践”,直接和你说怎么做;vue 的文档写得真的很好,甚至他连“最佳实践”都在文档上;vue 官方提供的插件基本上都是比较好用的。

如果你想从 vue 开发平滑过渡到 react 开发,可以了解一下 “react + dva”,它和 vuex 一样,设计理念都是来源于 elm,如果你很熟悉 vue + vuex 的开发,它可以让你很几乎没有成本、无痛过渡到 react 开发来。

参考

https://zh-hans.reactjs.org/

https://cn.vuejs.org/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值