前言
最近在写一个项目,在写react的过程中遇到过很多坑,现在总结一下,为以后的项目作参考.另外借此项目来比较一下 vue.js 和 react.js 之间的一些异同.
先说说组件
刚刚开始写组件的时候,感觉难度不大(跟vue差不多)。最有意思的应该是jsx语法,个人感觉,jsx的功能性确实比vue的template更强,而且可读性更高.
举个栗子
// vue
<p :id="text" :class="{'active':isActive}" v-text="'hello! ' + msg"></p>
// jsx
<p id={text} className={isActive && 'active'}>hello !{msg}</p>
- 在jsx里面没有指令,而且jsx里面
{}
代表要执行的js语句,它的效果类似return
,它会有返回值.这样的话,更好理解jsx的内容,jsx里面的dom不是真正的dom,只是一种表示dom的语法,{}
里面的内容可以完全理解为js,这种整个jsx就可以完成理解为原生js写的html模版. - 属性计算的部分,vue里面需要在属性名前面加
:
,在jsx里面则不需要. - 另外,在vue里面的dom的
contentText
不使用{{}}
来渲染,使用因为在vue页面生成之前,模版语法部分没有渲染出来,就会在页面上先出现{{content}}
,再一闪变成真正的文本内容.
再举个数组遍历渲染的栗子
// vue
<ul>
<li v-for="(item,index) in list" :key="index" v-if="showItem(item)">
<span v-text="item.label"></span>
</li>
</ul>
// vue的methods属性
methods:{
showItem(item){
return item.label.indexOf('abc') !== -1
}
}
// jsx
<ul>
{list.map((item,index) => {
return item.label.indexOf('abc') !== -1 && (
<li key={index}>
<span>{item.label}</span>
</li>
)
})}
</ul>
你会发现,在一些比较简单渲染需求时,使用vue的template会比较简单直接,而且很易懂.但是如果涉及一些比较复杂的逻辑处理渲染,jsx更直观,因为jsx的语法跟js的差异不大,相当于用js来描述需要如何渲染dom结构.当然jsx并不是说可以完成使用js的语法来写dom,{}
里面只能是一个表达式,所以像if else
或者switch
这种语法在{}
是不能用的.
redux
在写redux的时候,不是很习惯。后来慢慢的去适应。由于还用到了saga
,以至于书写方法上与redux官方的推荐的有所不同。
‘action type’定义的不同类型。
- action ===> reducer
- action ===> saga ===> reducer
第一种情况:触发action
之后直接commit一个reducer
。
// action
{type:'do/update-some-data',payload}
第二种情况,触发的action
会被saga
拦截,然后saga
完成一定的操作后(一般是从后台获取数据);put
一个action
,作用到reducer
。
// saga action
{type:'start/get-some-data',payload}
// reducer action
{type:'success/get-some-data',payload}
{type:'failed/get-some-data',payload}
{type:'error/get-some-data',payload}
一些代码书写规范
因为以前在写代码的时候一直都没有确定好一个规范,导致代码风格一直有变化(已经被同事吐槽好几次了)。后来在这个项目里面看了其他的同事的代码再结合网上推荐的一些代码规范,目前总结出一些小心得(也不算什么心得)。
1.还是从组件开始
- 组件注释
- 模块引入
- 内部方法
- 组件类定义
- redux select
- export
1.注释的问题我个人一直都重视的,一份好的注释可以让别人在开始看代码之前就能对内容有一个大概清晰的了解。
/**
* @name:组件名称
* @author:谁维护的
* @version:2017-12-28 日期或者版本号
* @description:描述
* 你会发现没有’param‘,这个部分在组件定义的地方会提到。
*/
这些只是基本的信息,还可以添加其他你想加的内容。
2.模块引入的部分一般有这些分类
- 依赖。例如库或者插件
- 子组件
- 资源文件。例如默认的图标或者背景图什么的。
3.内部方法
内部方法一般是针对该组件需要的功能而定义的,而且不想跟类一起export出去。比如,组件里拿到后台的一个对象数组,需要根据这个数组的信息计算出一个值,然后在组件中使用。
如果这个方法在多个组件中使用到的话,还可以把它提到utils
文件夹中。
4.组件定义
一般情况下,组件都会使用类来定义。比如:
class MyComponent extends Component{
static defaultProps = {
a:0,
b:1
}
constructor(props) {
super(props)
this.state = {
c:2,
d:3
}
}
handleClick = () = >{
// some stuff
}
render() {
const {a,b} = this.props
const {c,d} = this.state
const e = false
return(
<div>
<div a={a} b={b}></div>
<div {...{a,c}}></div>
<div {...this.props} {...this.state}></div>
e && {<div>some code</div>}
</div>
)
}
}
首先,为啥子要写defaultProps
?我觉得,有两点:
- 知道在使用这个组件的时候,应该传入哪些参数,都有什么意义。这样比在组件头注释写更具体。
- 设置默认值,避免使用时没有传参,导致一些bug。
state
就略过了。
类的方法。这里使用了箭头函数
来定义,主要是为了使用this
,因为大多数情况下,handle里面都会调用this.setState
,这样写就不需要去constructor
一个个bind(this)
了。其实如果方法里面没有使用指向类的this
,用函数定义的方式也是可以的。
render部分。我一般习惯将使用到的props
和state
以及其他的数据全部在return
前定义出来。这样会更清晰明白组件里面使用了哪些数据。
另外是给元素设置属性的一些小技巧。平时最常用的方式是这样的key={value}
,还可以使用对象解构的方式设置属性。
redux seletct & export
说到redux
一定要扯上vuex
(看完下面的内容,如果有不同意见的战友,请不要打我)。
这里先从组件部分来看一下redux
和vuex
的区别。在组件里面主要是看如何让当前组件使用到store
中的数据和方法。
// react
import React, { Component } from 'react'
import { connect } from 'react-redux'
import * as actions from '../actions'
import { bindActionCreators } from 'redux'
class MyComponent extends Component{}
function mapStateToProps(state){
return {
...state,
stateOne:state=>state.stateOne,
stateTwo:state=>state.stateTwo
}
}
functino mapDispatchToProps(dispatch){
return {
...bindActionCreators(actions,dispatch),
handleOne:(arg)=>dispatch(actions.handleOne(arg)),
handleTwo:(arg)=>dispatch(actions.handleTwo(arg))
}
}
export connect(mapStateToProps,mapDispatchToProps)(MyComponent)
react里面要使用connect
方法把state和dispatcher和当前组件连接起来.
// vue
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('theModule')
export default {
computed:{
...mapState(['stateOne','stateTwo']),
...mapState({
stateThree:state=>state.theModule.stateThree,
stateFour:state=>state.theModule.stateFour
})
},
methods:{
...mapActions(['handleOne','handleTwo']),
...mapActions({
handleThree:'actionThree',
handleFour:'actionFour'
})
}
}
在vue里面也有相应的辅助函数,而且vuex的store
包含来数据和方法,在根组件注入之后,所有的子组件都可以通过this.$store
使用,辅助函数只是用来过滤而已.
待续…