框架对比
/ | Vue | React |
---|---|---|
单文件直接引入 | vue.js | react.js + react-dom.js + babel.js |
构建项目 | vue-cli | create-react-app |
虚拟DOM | √ | √ |
虚拟DOM区域(挂载区域) | el 参数值 | ReactDOM.render() 第二个参数值 |
数据驱动 | √ | √ |
Model数据源 | 初始化,定义在data:{} 或 data () { return {} }里 | 在state里 constructor () { this.state = {} } |
数据渲染 | {{ }} 插值渲染 支持表达式 | JSX { } 表达式 |
列表渲染 | v-for | 在JSX 内构建一个元素集合 {this.state.arr.map((item,index)=><li key={index}>{item}</li>)} |
条件渲染 | v-if | {this.state.show? <h1>条件渲染</h1> : null} |
子组件内元素渲染 | slot | this.props.children |
动态绑定 | v-bind | title={this.state.title} |
数据更新 | 重新赋值 this.id = xxx; / this.$set() | this.setState({id:xx}) 更新数据 |
指令 | 有 | 无 |
计算属性 | 有 | 无 |
添加class | class / :class | 使用className className=“red” |
动态切换class | :class="[show? ‘class1’: ‘class2’]" | className={this.state.show ? “class1” : “class2”} |
style行间 | style / :style | jsx写法 style={{color:“pink”}} |
css作用域(私有) | style scoped | CSS Modules |
ref | √ | √ |
事件写法 | @click=“clickFn” | onClick={this.clickFn.bind(this)} |
事件处理函数 | methods: {}里 | 与render(){} 方法同级 |
生命周期钩子函数 | created() mounted() 等 | componentDidMount() componentDidUpdate() 等 |
创建组件 | Vue.component全局 / components:{} 局部 | function组件 / class组件 正好对应 Redux中的UI组件和容器组件,一个负责内容展示,一个负责操作数据 |
组件定义规则 | 1.kebab-case (短横线分隔命名) 2.PascalCase (大驼峰式) | 为了区分原生标签,组件必须大写 |
组件特点 | .vue文件 分html、js、css三块 | all in js |
组件自身作用域 | 有 data里的数据属于组件本身 | 有 state数据属于自身类 |
过渡动画 | transition组件 | 使用react-transition-group |
数据流向 | 单向数据流 | 单向数据流 |
数据双向绑定 | v-model | 受控组件(onChange & value ) |
属性监听 | watch | static getDerivedStateFromProps(props, state) 拿到即将更新后的props和state。只能自己去手动对比 |
监听DOM变化 | nextTick() | 无,只能从componentDidUpdate()取DOM,类似Vue 的updated()生命周期 |
父组件向子组件传值 | 同为单向数据流,props往下传值 - 需要在子组件接收props:[‘xx’],然后就可以使用xx值 | 同为单向数据流,props往下传值 - 直接使用this.props.xx 取到值 |
props数据类型限定 | 在props对象中限定具体类型 | PropTypes 需单独引包 |
组件跨级传值 | context | 无 |
子组件向父组件传值 | 均使用回调函数通知父组件。子组件this.$emit触发父组件事件,父级在监听事件中获取子组件传递的值 | 均使用回调函数通知父组件。子组件this.props.xx 触发父组件事件,父级在监听事件中获取子组件传递的值 |
路由对比
/ | vue-router | react-router |
---|---|---|
路由 | vue-router | react-router |
状态管理对比
/ | Vuex | React-Redux |
---|---|---|
状态 | state | state |
状态仓库 | Store | Store |
状态的计算属性 | 有 state的计算属性,getters(其实就是基于Vue的计算属性) | 无 |
Store单一数据源 | √ | √ |
定义Store | new Vuex.Store() | createStore(reducers) 需要reducers纯函数 |
组件如何拿到state | new Vue() 把store注入到store选项上,成为this实例的属性,让各个组件都可以拿到 | 给根组件套上标签,在顶层传入store, 子孙组件通过context拿到state,但是UI组件必须使用connect()方法进行装饰,在使用mapStateToProps映射后,取值 |
各自框架中获取state | $store.state.xx (template) this.$store.state.xx (js) | this.props.xx |
修改状态方法 | The only way to actually change state in a Vuex store is by committing a mutation. 提交 mutation | The only way to change the state tree is to emit an action, an object describing what happened. 触发action,一个描述发生什么的对象 |
修改状态(同步) | view——>commit——>mutations——>state变化——>view变化(同步) | view——>actions——>reducer——>state变化——>view变化(同步) |
修改状态(异步) | view——>dispatch——>actions——>mutations——>state变化——>view变化(异步) | view——>actions——>redux middleware——>actions——>reducer——>state变化——>view变化 (异步) |
同步/异步处理方式 | 提出mutations同步,actions异步,两者相不干扰 | 同步dispatch进入reducer改状态,异步需要配置中间件,在进入dispatch()后,在中间件层做处理。 Dva借鉴了Vuex |
原store更改状态写法 | store.commit() / store.dispatch() | store.dispatch() |
各自框架中的修改状态 | 因store挂载到实例下,所以可以直接使用实例的对象方法。 this.$store.commit() / this.$store.dispatch() | mapDispatchToProps映射Action后,调用一个action creator函数 this.props.Fn(),去执行dispatch操作 |
更新状态 | mutations 直接更新状态。 非纯函数 | reducer返回新状态,并不是去更新值。 纯函数 |
状态变化如何更新View层 | Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。 | 组件订阅mapStateToProps,当映射state的部分值改变时会执行this.setState(),重新渲染View |
模块化 | 有 多个module,类似一个小store,每个小module有自己的state,actions等 | 无 Dva有namespace |
基于各自框架
/ | Vue | React |
---|---|---|
UI库 | element-ui iview 等 | Ant-design 等 |
多端统一开发框架 | uni-app | Taro |