// ... render (h) { return ( <div // normal attributes or component props. // DOM properties are prefixed with `domProps` domPropsInnerHTML="bar" // event listeners are prefixed with `on` or `nativeOn` onClick={this.clickHandler} nativeOnClick={this.nativeClickHandler} // other special top-level properties class={{ foo: true, bar: false }} style={{ color: 'red', fontSize: '14px' }} key="key" ref="ref" // assign the `ref` is used on elements/components with v-for refInFor slot="slot"> </div> ) }
但是,Vue的jsx语法无法支持Vue的内建指令,唯一的例外是v-show,该指令可以使用v-show={value}的语法。大多数指令都可以用编程方式实现,比如v-if就是一个三元表达式,v-for就是一个array.map()等。
如果是自定义指令,可以使用v-name={value}语法,但是该语法不支持指令的参数arguments和修饰器modifier。有以下两个解决方法:
将所有内容以一个对象传入,如:v-name={{ value, modifier: true }}
使用原生的vnode指令数据格式,如:
const directives = [ { name: 'my-dir', value: 123, modifiers: { abc: true } } ] return <div {...{ directives }}/>
那么,我们什么时候使用jsx,什么时候template呢?很明显,面对那么复杂多变的视图渲染,我们使用jsx语法更能得心应手,面对简单的视图,我们使用template能开发得更快。
状态管理
特性对比
针对状态管理,Vue的Vuex和React的Redux很雷同,都是Flow数据流。
对于React来说,state需要通过mapStateToProps将state传入到组件的props中,action需要通过mapDispatchToProps将action注入到组件的props中,然后在组件的props中获取并执行。
而在Vue中,store在组件的$store中,可以直接this.$store.dispatch(actionType)来分发action,属性也可以通过mapState,或者mapGetter把state或者getter挂载到组件的computed下,更粗暴的可以直接this.$store.state或者this.$store.getter获取,非常方便。
组件改造
我们为了更贴切于es6的class写法,更好的配合vue-class-component,我们需要通过其他的方式将store的数据注入到组件中。
vuex-class
vuex-class,这个包的出现,就是为了更好的讲Vuex与class方式的Vue组件连接起来。
如下,我们声明一个store
import Vuex from 'vuex'; const store = new Vuex.Store({ modules: { foo: { namespaced: true, state: { text: 'hello world', }, actions: { setTextAction: ({commit}, newText) => { commit('setText', newText); } }, mutations: { setText: (state, newText) => { state.text = newText; } } } } })
针对这个store,我们改写我们上一章节的组件
<template> <div> <h1>{{title}}</h1> <span>{{text}}<span> <button @click="setText">按钮</button> </div> </template> <script> import { Vue, Component, Watch, Prop } from 'vue-property-decorator'; import { namespace } from 'vuex-class'; const fooModule = namespace('foo'); @Component export default class Demo extends Vue { @fooModule.State('text') text; @fooModule.Action('setTextAction') setTextAction; @Prop({type: String, default: 'Vue Demo'}) title; @Watch('title') titleChange(newTitle, oldTitle) { console.log(`标题从 ${oldTile} 变为了 ${newTitle}`) } setText(e) { this.setTextAction('点击了按钮'); } } </script>
这里可以发现,store声明了一个foo模块,然后在使用的时候从store中取出了foo模块,然后使用装饰器的形式将state和action注入到组件中,我们就可以省去dispatch的代码,让语法糖帮我们dispatch。这样的代码,看起来更贴切与面向对象。。。好吧,我承认这个代码越写越像Java了。
然而,之前的我并不是使用Redux开发React的,而是Mobx,所以这种 dispatch -> action -> matation -> state 的形式对我来说也不是很爽,我还是更喜欢把状态管理也以class的形式去编写,这个时候我又找了另外一个包vuex-module-decorators来改写我的store.module。
下面我们改写上面的store: