v-if 和 v-for
只要在原生的 JavaScript 中可以轻松完成的操作,Vue 的渲染函数就不会提供专有的替代方法。比如,在模板中使用的 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>
这些都可以在渲染函数中用 JavaScript 的 if/else 和 map 来重写:
<script>export default {props:{items:{type:Array,},},data(){return {}},render(h){if(this.items.length){return h('ul',this.items.map(ele =>{return h('li',{key:ele,//尽管存在prop和事件,但是有时候我们仍可能需要在JS里直接访问一个子组件,那么此时,我们可以通过 ref 特性为子组件赋予一个ID引用:ref:'li',refInFor:true,}, ele)}))}else{return h('p','No items found')}}}</script>
v-model
渲染函数中没有与 v-model 的直接对应——你必须自己实现相应的逻辑:
管网中子组件的代码
props: ['value'],render: function (createElement) {var self = thisreturn createElement('input', {domProps: {value: self.value},on: {input: function (event) {self.$emit('input', event.target.value)}}})}
父组件实现v-model
<template><div id="app"><mode :value = "value" v-model="value"></mode>{{ value }}</div></template><script>const mode = ()=> import('./components/mode')export default {name: 'App',components: {mode},data(){return{value:''}}}</script>
事件&案件修饰符
对于 .passive、.capture 和 .once 这些事件修饰符,Vue 提供了相应的前缀可以用于 on:
| 修饰符 | 前缀 |
|---|---|
.passive |
& |
.capture |
! |
.once |
~ |
.capture.once 或.once.capture |
~! |
例如:
on: {'!click': this.doThisInCapturingMode,'~keyup': this.doThisOnce,'~!mouseover': this.doThisOnceInCapturingMode}
对于所有其它的修饰符,私有前缀都不是必须的,因为你可以在事件处理函数中使用事件方法:
| 修饰符 | 处理函数中的等价操作 |
|---|---|
.stop |
event.stopPropagation() |
.prevent |
event.preventDefault() |
.self |
if (event.target !== event.currentTarget) return |
按键:.enter, .13 |
if (event.keyCode !== 13) return (对于别的按键修饰符来说,可将 13 改为另一个按键码) |
修饰键:.ctrl, .alt, .shift, .meta |
if (!event.ctrlKey) return (将 ctrlKey 分别修改为 altKey、shiftKey 或者 metaKey) |
这里是一个使用所有修饰符的例子:
on: {keyup: function (event) {// 如果触发事件的元素不是事件绑定的元素// 则返回if (event.target !== event.currentTarget) return// 如果按下去的不是 enter 键或者// 没有同时按下 shift 键// 则返回if (!event.shiftKey || event.keyCode !== 13) return// 阻止 事件冒泡event.stopPropagation()// 阻止该元素默认的 keyup 事件event.preventDefault()// ...}}
自定义指令
注意此处生成的是HTML代码是让html元素使用vue的自定义指令并不是如何实现指定所需要的效果
案例:
<script>// 效果// <template>// <div>// <input type="text" v-slice:5.number="content">// {{ content }}// </div>// </template>export default {data(){return {content:"12456",}},directives:{// 自定义指令 v-slice:5.number// 实现输入框中只能输入数字且长度有自定义指令的参数定义'slice':{bind (el, binding, vnode) {const vm = vnode.context;let { value, expression, arg, modifiers } = binding;if(modifiers.number) {value = value.replace(/[^0-9]/g, '');}el.value = value.slice(0, arg);vm[expression] = value.slice(0, arg);el.oninput = function (e) {let inputVal = el.value;if(modifiers.number) {inputVal = inputVal.replace(/[^0-9]/g, '');}el.value = inputVal.slice(0, arg);vm[expression] = inputVal.slice(0, arg);}},update (el, binding, vnode) {const vm = vnode.context;let { value, arg, expression, modifiers } = binding;if(modifiers.number) {value = value.replace(/[^0-9]/g, '');}el.value = value.slice(0, arg);vm[expression] = value.slice(0, arg);},}},// 使用render函数生成最上面template代码中的效果render(h){return h('div',[h('input',{directives: [{name: 'slice', // v-slicevalue: this.content, // v-slice="content"expression: 'content', //字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。arg: 5, // v-slice:5="content"modifiers: {number: true // v-slice:5.number="content"},}]}),this.content,])}}</script>
插槽
具名插槽
所使用的的api: vm.$slot.具名插槽的名字
vue官方给出解释
父组件代码
<script>// html代码示例// <template>// <div>// <slot>我是默认插槽</slot>// <slot name="header">我是头部插槽header</slot>// </div>// </template>export default {render(h){return h('div',[h('base-slot',[h('p',{domProps:{innerText:'我是默认插槽'},slot:'default' // 具名插槽的name})]),h('i',{domProps:{innerText:'我是插槽header'},slot:'header'// 具名插槽的name}),])}}</script>
v-slotd的render代码
<script>// <template>// <div>// <slot></slot>// <slot name="header"></slot>// </div>// </template>export default {data(){return{msg:'Im a slot'}},render(h){return h('div',[this.msg,this.$slots.header,this.$slots.default])}}</script>
作用域插槽
获取子组件的数据,
需要使用: vm.$scopedSlots
vue官方的讲解:
父组件的代码
<script>//最终的html代码// <template>// <div>// <div-slot2>// 子组件中template的代码// <div>// <strong> {{name}} </strong>// </div>// </div-slot2>// </div>// </template>export default {data(){return{obj:{name:'张三',age:'123',}}},render(h){return h('div',[this.$scopedSlots.default({obj:this.obj,})])}}</script>
子组件的代码//
<script>import baseSlot2 from './base-slot2'export default {components:{baseSlot2,},render(h){return h('div',[h('base-slot2',{scopedSlots:{default:function(props){const {name,age} = props.objreturn h('strong',name)}}})])}}</script>
