3.3.4 使用 JavaScript 代替模板功能
优质
小牛编辑
124浏览
2023-12-01
v-if
和v-for
由于使用原生的 JavaScript 来实现某些东西很简单,Vue 的 render 函数没有提供专用的 API。比如,template 中的v-if
和v-for
:
<ul v-if="items.length"> <li v-for="item in items">{{ item.name }}</li> </ul> <p v-else>No items found.</p>
这些都会在 render 函数中被 JavaScript 的if
/else
和map
重写:
props: ['items'], render: function (createElement) { if (this.items.length) { return createElement('ul', this.items.map(function (item) { return createElement('li', item.name) })) } else { return createElement('p', 'No items found.') } }
v-model
render 函数中没有与v-model
相应的 api - 你必须自己来实现相应的逻辑:
props: ['value'], render: function (createElement) { var self = this return createElement('input', { domProps: { value: self.value }, on: { input: function (event) { self.$emit('input', event.target.value) } } }) }
这就是深入底层要付出的,尽管麻烦了一些,但相对于v-model
来说,你可以更灵活地控制。
事件 & 按键修饰符
对于.passive
、.capture
和.once
事件修饰符, Vue 提供了相应的前缀可以用于on
:
Modifier(s) | Prefix |
---|---|
.passive | & |
.capture | ! |
.once | ~ |
.capture.once or.once.capture | ~! |
例如:
on: { '!click': this.doThisInCapturingMode, '~keyup': this.doThisOnce, '~!mouseover': this.doThisOnceInCapturingMode }
对于其他的修饰符,前缀不是很重要,因为你可以在事件处理函数中使用事件方法:
Modifier(s) | Equivalent in Handler |
---|---|
.stop | event.stopPropagation() |
.prevent | event.preventDefault() |
.self | if (event.target !== event.currentTarget) return |
Keys: .enter ,.13 | if (event.keyCode !== 13) return (change13 toanother key codefor other key modifiers) |
Modifiers Keys:.ctrl ,.alt ,.shift ,.meta | if (!event.ctrlKey) return (changectrlKey toaltKey ,shiftKey ,ormetaKey , respectively) |
这里是一个使用所有修饰符的例子:
on: { keyup: function (event) { // 如果触发事件的元素不是事件绑定的元素 // 则返回 if (event.target !== event.currentTarget) return // 如果按下去的不是 enter 键或者 // 没有同时按下 shift 键 // 则返回 if (!event.shiftKey || event.keyCode !== 13) return // 阻止事件冒泡 event.stopPropagation() // 阻止该元素默认的 keyup 事件 event.preventDefault() // ... } }
插槽
你可以从this.$slots
获取 VNodes 列表中的静态内容:
render: function (createElement) { // `<div><slot></slot></div>` return createElement('div', this.$slots.default) }
还可以从this.$scopedSlots
中获得能用作函数的作用域插槽,这个函数返回 VNodes:
props: ['message'], render: function (createElement) { // `<div><slot :text="message"></slot></div>` return createElement('div', [ this.$scopedSlots.default({ text: this.message }) ]) }
如果要用渲染函数向子组件中传递作用域插槽,可以利用 VNode 数据中的scopedSlots
域:
render: function (createElement) { return createElement('div', [ createElement('child', { // pass `scopedSlots` in the data object // in the form of { name: props => VNode | Array<VNode> } scopedSlots: { default: function (props) { return createElement('span', props.text) } } }) ]) }