这是我参与更文挑战的第5天,活动详情查看: 更文挑战
前言
因个人爱好所以在一个主导项目中,擅自使用了看了没几天的React来开发(血的教训)。
所以想列出一些Vue和React常见的写法对比。
监听props修改state
这个真的是,让人快乐的不行, 在Vue当中直接使用watch监听钩子,或者通过updated或beforeUpdate生命周期监听特定属性就可以。
但是React17中 componentWillUpdate 钩子取消了(微笑)
用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
生命周期
这个其实本来不太想写,但是既然要提两者的语法差异,那就不得不来一下了
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() {}
}