十二、虚拟 DOM 和 render() 函数(2)
创始人
2024-02-11 20:06:47
0

本章概要

  • 用普通 JavaScript 代替模板功能
    • v-if 和 v-for
    • v-model
    • v-on
    • 事件和按键修饰符
    • 插槽
  • JSX
  • 实例:帖子列表

12.3 用普通 JavaScript 代替模板功能

原先在模板中可以使用的一些功能在 render() 函数中没有再提供,需要自己编写 JavaScript 代码来实现。

12.3.1 v-if 和 v-for

只要普通 JavaScript 能轻松完成的操作,Vue 的 render() 函数就没有提供专有的替代方案。例如,在使用 v-if 和 v-for 的模板中:

  • {{ item.name }}

No items found.

在 render() 函数中可以使用 JavaScript 的 if/else 和 map 实现相同的功能。如下:

props:['items'],
render(){if(this.items.length){return Vue.h('ul',this.items.map((item) => {return Vue.h('li',item.name)}))}else{return Vue.h('p','No items found.')}
}

12.3.2 v-model

在 render() 函数中没有与 v-model 指令直接对应的实现方案,不过v-model 指令在模板编译期间会被扩展为 modelValue 和 onUpdate:modelValue prop ,按照 v-model 的内在逻辑,自己实现即可,如下:

props:['modelValue'],
render(){return Vue.h(SomeComponent,{modelValue:this.modelValue,'onUpdate:modelValue':value => this.$emit('update:modelValue',value)})
}

12.3.3 v-on

必须为事件处理程序提供一个正确的 prop 名称。例如,要处理 click 事件,prop 名称应该是 onClick。代码如下:

render(){return Vue.h('div',{onClick:$event => console.log('clicked',$event.target)})
}

12.3.4 事件和按键修饰符

对于 .passive、.capture 和 .once 这些事件修饰符,可以使用驼峰命名法将他们连接到事件名之后。如下:

render(){return Vue.h('input',{onClickCapture:this.doThisInCapturingMode,onKeyupOnce:this.doThisOnce,onMouseoverOnceCapture:this.doThisOnceInCapturingMode})
}

对于其它的事件和按键修饰符,则不需要特殊的 API ,因为在处理程序中可以使用事件方法实现相同的功能,如下:
与修饰符等价的事件方法

修饰符处理函数中的等价操作
.stopevent.stopPropagation()
.preventevent.preventDefault()
.selfif(event.target!== event.currentTarget) return
按键:.enter、.13if(event.keyCode!==13) return (对于其他的按键修饰符,可将13改为其对应的按键码)
修饰符:.ctrl、.alt、.shift、.metaif(!event.ctrlKey) return (可将 ctrlKey 分别修改为 altKey、shiftKey、mateKey)

下面是一个使用所有修饰符的例子:

render(){return Vue.h('input',{onKeyUp:event => {// 如果触发事件的元素不是事件绑定的元素,则返回if(event.target !== event.currentTarget) return// 如果按下的不是 Enter 键(13)或没有同事按下 Shift 键,则返回if(!event.shiftKey || event.keyCode !== 13) return// 阻止事件传播event.stopPropagation()// 阻止该元素默认的 keyup 事件处理event.preventDefault()// ...}})
}

12.3.5 插槽

通过 this.slots 可以访问插槽的内容,插槽的内容是 VNode 数组。代码如下:

render(){// `
`return Vue.h('div',{},this.$slots.default()) } // 访问作用域插槽 props:['message'], render(){// `
`return Vue.h('div',{},this.$slots.default({text:this.message})) }

如果要使用 render() 函数将插槽传递给子组件,可以编写下面的代码:

render (){// `
{{ props.text }}
`return Vue.h('div',[Vue.h(Vue.resolveComponent('child'),{},// 将 slots 作为子对象传递// 格式为:{ name:props => VNode | Array }{default:(props) => Vue.h('span',props.text)})]) }

12.4 JSX

这时候会发现,即使是简单的模板,在 render() 函数中编写也很复杂,而且模板中的 DOM 结构面目全非,可读性很差。当模板比较复杂,元素之间嵌套的层级较多时,在 render() 函数中一层层嵌套的 h() 函数也令人迷惑。

React 的 render() 函数使用 JSX 语法来简化模板的编写,使模板的编写变得和普通 DOM 模板一样简单。在 Vue 中,可以通过一个 Babel 插件让Vue 支持 JSX 语法,从而简化 render() 函数中的模板创建。

提示:
JSX 的全称是 JavaScript XML ,是一种 JavaScript 的语法扩展,用于描述用户界面。其格式比较像是模板语言,但事实上完全是在 JavaScript 内部实现的。

例如:对于下面 DOM 结构:

hello world
>

不使用 JSX 语法的 render() 函数实现如下:

Vue.h(Vue.resolveComponent('anchored-heading'),{level:1},{default:() => [Vue.h('span','hello'),'world']})

使用 JSX 语法的 render() 函数实现如下:

import AnchoredHeading from './AnchoredHeading.vue'
const app = createApp({render(){1}>hello world}
})
app.mount('#demo')

12.5 实例:使用 render() 函数实现帖子列表

首先是单个帖子的组件 PostListItem,如下:

// 子组件
app.component('PostListItem', {props: {post: {type: Object,required: true}},render() {return Vue.h('li', [Vue.h('p', [Vue.h('span',// 这是元素的内容'标题:' + this.post.title + ' | 发帖人:' + this.post.author + ' | 发帖时间:' + this.post.date + ' | 点赞数:' + this.post.vote),Vue.h('button', {onClick: () => this.$emit('vote')}, '赞')])]);}
});

一定要清楚 h() 函数的 3 个参数的作用,因为后面两个参数都是可选的,所以要主义区分哪部分是第二个参数传参,哪部分是第三个参数传参。
简单的区分方式就是看对象传参还是数组传参,如果是对象传参,就是第二个参数(设置元素的属性信息);如果是数组传参,就是第三个参数(设置子节点信息)。
完整代码如下:



渲染结果如下:
在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...