Vue vs React,语法差异之处

904 阅读3分钟

这是我参与更文挑战的第5天,活动详情查看: 更文挑战

前言

因个人爱好所以在一个主导项目中,擅自使用了看了没几天的React来开发(血的教训)。

所以想列出一些Vue和React常见的写法对比。

监听props修改state

这个真的是,让人快乐的不行, 在Vue当中直接使用watch监听钩子,或者通过updated或beforeUpdate生命周期监听特定属性就可以。

但是React17componentWillUpdate 钩子取消了(微笑)

componentUpdated钩子中修改state又会继续触发componentUpdated, 直接栈溢出(微笑)

终于,被我找到了它,能解决这一死循环的写法。 并不会修改其他属性

// React
  state = {
      type: false,
      name: 'test'
  }
  static getDerivedStateFromProps(nextProps, prevState) {
    // 注: 每次修改props 或state都会触发这个生命周期,所以要做条件判断
    if (!Array.isArray(props.list) && !prevState.type) {
      // return 的对象用于修改state, 不修改state只是监听,可以返回 null
      return { type: nextProps.list.type};
    }
    // 没有达到预期值,则不修改,避免意料之外的情况
    return null;
  }
  // console.log(this.state) {type: '全部', name: 'test'}
// Vue
watch{
    type(new, old){
        this.type = new;
    },
    name{ // 深度监听, 适合用在对象/数组上
        handle(new, old){
            this.name = new;
        },
        deep: true
    }
}

遍历数组与对象

在Vue当中,使用v-for属性快乐就完事

但是在React中, 遍历数组和遍历对象是不一样的

// React
<div className="box">
    { // 遍历数组
        arr.map(item => {
            return (<div></div>)
        })
    }
    { // 遍历对象
        Object.keys(obj).map(item => {
            return (<div></div>)
        })
    }
</div>
// Vue
<div v-for="item in data">
    // ... 略
</div>

渲染HTML内容

// react
<div dangerouslySetInnerHTML={{__html: content}}></div>
// Vue
<div v-html="content"></div>

设置路由别名(不暴露eject)

React设置路由别名相对麻烦一些, 需要下载两个依赖以及修改package.json的scripts部分

如果只是配置路由别名,没必要通过eject命令暴露所有配置文件,相比较其他教程也简单很多

@components这种别名格式只是我的个人习惯, 可以去掉@符号,配置个性化的别名

// react
// 安装 customize-cra  react-app-rewired
// 1、根目录下创建 config-overrides.js
const { override, addWebpackAlias } = require("customize-cra")
const path = require("path");

module.exports=override(

   //引入插件写相关配置
  addWebpackAlias({
    "@" : path.resolve(__dirname, "src"),
    "@utils": path.resolve(__dirname, "src/utils")
  })
)
// 2、修改package.json 之后重启下
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  },
const path = require('path');

function resolve(dir) {
  return path.join(__dirname, dir);
}
module.exports = {
  lintOnSave: true,
  chainWebpack: (config) => {
    config.resolve.alias
      .set('@', resolve('src'))
      .set('@utils',resolve('src/utils'))
  }
};

调用方法及传参

// react
// 1
<div onClick={() => this.click(id)} ></div>
// 2 
<div onClick={this.click.bind(null, id) ></div>
// Vue
<div @click="click(id)"></div>

获取路由参数

// react
componentDidMount(){
    // index/:home index/1
    this.props.match.params.home
}
// Vue
    this.$route.query.home   // /index?home=1
    this.$route.params.home  // /index/:home  /index/1

生命周期

这个其实本来不太想写,但是既然要提两者的语法差异,那就不得不来一下了

image.png

react17的声明周期,没有图,凑合一下?

class A extends React.Component {
  // 用于初始化 state
  constructor() {}
  // 用于替换 `componentWillReceiveProps` ,该函数会在初始化和 `update` 时被调用
  // 因为该函数是静态函数,所以取不到 `this`
  // 如果需要对比 `prevProps` 需要单独在 `state` 中维护
  static getDerivedStateFromProps(nextProps, prevState) {}
  // 判断是否需要更新组件,多用于组件性能优化
  shouldComponentUpdate(nextProps, nextState) {}
  // 组件挂载后调用
  // 可以在该函数中进行请求或者订阅
  componentDidMount() {}
  // 用于获得最新的 DOM 数据
  getSnapshotBeforeUpdate() {}
  // 组件即将销毁
  // 可以在此处移除订阅,定时器等等
  componentWillUnmount() {}
  // 组件销毁后调用
  componentDidUnMount() {}
  // 组件更新后调用
  componentDidUpdate() {}
  // 渲染组件函数
  render() {}
}