Appearance
jsx 语法
jsx 与 渲染函数
jsx 就是一种语法糖,通过 babel 编译后就是渲染函数,以下两段代码等价。
jsx 写法
jsx
render (h) {
return (
<div
id="foo"
propsOnCustomEvent={this.customEventHandler}
domPropsInnerHTML="bar"
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
class={{ foo: true, bar: false }}
style={{ color: 'red', fontSize: '14px' }}
key="key"
ref="ref"
refInFor
slot="slot">
</div>
)
}
渲染函数写法
js
render (h) {
return h('div', {
props: { onCustomEvent: this.customEventHandler },
attrs: { id: 'foo' },
domProps: { innerHTML: 'bar' },
on: { click: this.clickHandler },
nativeOn: { click: this.nativeClickHandler },
class: { foo: true, bar: false },
style: { color: 'red', fontSize: '14px' },
key: 'key',
ref: 'ref',
refInFor: true,
slot: 'slot'
})
}
jsx 相较于渲染函数对 props、domProps、on、native 配置项做平铺处理,使用对应前缀+属性名作为属性传入。
指令
v-show 是唯一在 jsx 中写法支持的指令(babel6 以下)
jsx
<div v-show={true}>babel6 以下 jsx 唯一支持的指令</div>
v-if 使用三元运算符实现
往往认为 v-if
和 v-else
成对出现,所以使用三元运算符。
jsx
<div>{true ? <span>三元运算符</span> : <span>不展示</span>}</div>
v-for 使用数组 + map 方法实现
jsx
<div>
{[1, 2, 3].map(item => (
<div>{item}</div>
))}
</div>
自定义指令
用 jsx 写自定义指令确实有些麻烦,完全就是渲染函数的写法。
jsx
const directives = [{ name: 'demo', value: 123, modifiers: { abc: true } }]
return <div {...{ directives }}></div>
// 为什么这样就不行
return <div directives={directives}></div>
以上两段端绑定指令代码应该是一致的,结果却第二种绑定方式不行。其原因就是 directives 被解析到 attrs 属性中了,而其它的渲染函数选项(props,on 等)会正常解析,或许这算是一种 bug?
js
{
attrs: {
directives: [{ name: 'demo', value: 123, modifiers: { abc: true } }]
}
}
babel7+ 新增
新增对渲染函数参数支持
函数式组件 - 渲染函数
js
render(h, ctx) {
return h('div', ctx.data, ctx.children)
}
重点关注 ctx.data,该对象有两个重要属性 attrs 和 on,分别代表传入属性与事件。 jsx 支持渲染函数传参方式后,可以写成下面这种形式,并且两种写法等价。
jsx
render(h, ctx) {
return <div {...ctx.data}></div>
}
render(h, { data }) {
return <div attrs={data.attrs} on={data.on}></div>
}
jsx 函数式组件可直接写成函数
jsx
// 默认导出
export default ({ props }) => <p>hello {props.message}</p>
// 变量 - 一定使用大驼峰
const HelloWorld = ({ props }) => <p>hello {props.message}</p>
v-model 指令
jsx
<input vModel={this.value}></input>
v-on 指令
jsx
<input vOn:click={this.newTodoText} />
<input vOn:click={[this.newTodoText]} /> // 事件数组,逐个执行
指令修饰符使用下划线连接。
jsx
<input vModel_trim={this.value}></input>
<input vOn:click_stop_prevent={this.newTodoText} />
<input vOn:click_stop_prevent={[this.newTodoText]} />
注意
事件使用修饰符后,绑定值不可事件数组。
v-html 指令
实质就是 DOM 属性 innerHTML 赋值。
jsx
<p domPropsInnerHTML={html} />
其它
组件
使用组件引入即可,不用注册。
jsx
import MyComponent from './my-component'
export default {
render() {
return <MyComponent>hello</MyComponent>
}
}
插槽
jsx
<MyComponent>
<header slot="header">header</header>
<footer slot="footer">footer</footer>
</MyComponent>
作用域插槽
jsx
const scopedSlots = {
header: () => <header>header</header>,
footer: () => <footer>footer</footer>
}
<MyComponent scopedSlots={scopedSlots} />
注意
当使用了作用域插槽时,默认内容应该作为默认作用域插槽使用,否则有意想不到的 bug。
jsx
const scopedSlots = {
default: () => 默认文字,
header: () => <header>header</header>,
footer: () => <footer>footer</footer>
}
<MyComponent scopedSlots={scopedSlots}></MyComponent>