当前位置: 首页 > news >正文

Vue | Vue深入浅出——Vue中的render函数详解

1.render函数

在编写vue单文件的大多数情况下,我们都是使用template模板来创建HTML。然而在一些条件判断比较复杂的场景下,使用JavaScript去描绘HTML的生成逻辑会显得更加的简洁直观。

使用Vue官网的例子来简单说明:

如果自己在开发的时候,编写的每个标题(包括h1~h6)都需要带锚点,如下所示:

<h1><a name="hello-world" href="#hello-world">Hello world!</a>
</h1>

如果用template模板进行编写,会如下所示:

<template><h1 v-if="level === 1"><anchor :name="name" :content="content"></anchor></h1><h2 v-else-if="level === 2"><anchor :name="name" :content="content"></anchor></h2><h3 v-else-if="level === 3"><anchor :name="name" :content="content"></anchor></h3><h4 v-else-if="level === 4"><anchor :name="name" :content="content"></anchor></h4><h5 v-else-if="level === 5"><anchor :name="name" :content="content"></anchor></h5><h6 v-else-if="level === 6"><anchor :name="name" :content="content"></anchor></h6>
</template>
<script>
export default {name:'anchor-header',props:{level:Number,name:String,content:String},components:{'anchor':{props:{content:String,name:String},template:'<a :id="name" :href="`#${name}`"> {{content}}</a>'}}
}
</script>

显然代码冗长累赘。但如果用render函数来编写则如下所示:

<script>
export default {name:'anchor-header',props:{level:Number,name:String,content:String},render:function(createElement){const anchor={props:{content:String,name:String},template:'<a :id="name" :href="`#${name}`"> {{content}}</a>'}const anchorEl=createElement(anchor,{props:{content:this.content,name:this.name}})const el=createElement(`h${this.level}`,[anchorEl])return el}
}
</script>

可见通过render函数编写出的逻辑更加简洁且可读性更高。

每一个render函数都要return一个VNode类型的变量,是Vue中自定义的虚拟节点(virtual node),用于替换挂载元素$el。

Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

但自己实践在vue单文件实践后发现,如果同时存在templaterender,生成的html会以template的逻辑为主,奇怪。

上述例子的代码可以知道,render函数使用的场景是,要根据不同条件切换不同HTML标签,可以使用render函数。或者条件判断较多的template中,用渲染函数编写会让代码的可读性更高的情况下,也推荐使用render函数。

下面分析上面代码中出现的createElement函数。

2.createElement

createElement用于创建且return一个VNode类型的变量(虚拟节点),以下是该函数的传入参数:

(1)一个 HTML 标签名、组件选项对象或者resolve前面两种之一类型的async函数。必填。

例如,传入'div'表示想创建一个html标签为div的VNode;如果传入'transition'代表创建transition组件。

上面作为粒子的代码就是根据传入的类型为Number的参数level,用模板字符串拼接成标签名称。传入level为1则拼接出来的HTML标签名称为h1。代表要创建html标签为h1的VNode。

(2)所创建的VNode中所需参数为属性的数据对象。可选。

{class,style,attrs,props,domProps,on,nativeOn,directives:[{name,value,expression,arg,modifiers}],scopedSlots:{default:props=>createElement()},slot,key,ref,refInFor
}

大部分属性和vue组件中存在的属性的作用一样,我就只挑几个比较特殊的属性来说明:

**nativeOn:**用于监听原生事件,而不是组件内使用。例如:

nativeOn: {click: this.nativeClickHandler}

相当于@click.native="nativeClickHandler"

scopedSlots:定义作用域插槽的内部的内容:

格式为:{ name: props => VNode | Array<VNode> }

举一个例子:

<script>
export default {render (createElement) {var component = {template: `<div><slot></slot><slot name="foo"></slot></div>`}return createElement(component, {scopedSlots: {default: props => createElement('span', '456'),foo: props => createElement('span', '789')},})}
}
</script>

最后渲染出来的html效果如下:

<div><span>456</span><span>789</span>
</div>

scope:如果要生成的组件要插入到,需为插槽指定名称。

举个例子

<script>
export default {render (createElement) {var component = {template: `<div><slot></slot><slot name="foo"></slot></div>`}const childrenEl = createElement('span', { slot: 'foo' }, '123')return createElement(component, {scopedSlots: {default: props => createElement('span', '456')// foo: props => createElement('span', '789')      },}, [childrenEl])}
}
</script>

最后渲染出来的html效果如下:

<div><span>456</span><span>123</span>
</div>

注意:如果去掉上面例子的代码中// foo: props => createElement('span', '789')的注释,则slot="foo"插槽中显示内容依然为<span>789</span>

**  refInFor:**如果你在渲染函数中给多个元素都应用了相同的 ref 名,那么 `$refs.myRef` 会变成一个数组。

(3)子级虚拟节点 (VNodes)。如果传入的是VNode则要用列Array传入,另外也可以使用字符串来生成“文本虚拟节点”。可选。

3.函数式组件

函数式组件相比于一般的vue组件而言,最大的区别是非响应式的它不会监听任何数据,也没有实例(因此没有状态,意味着不存在诸如created,mounted的生命周期)。好处是因只是函数,故渲染开销也低很多。

把开头的例子改成函数式组件,代码如下:

<script>
export default {name:'anchor-header',functional:true, // 以functional:true声明该组件为函数式组件props:{level:Number,name:String,content:String},// 对于函数式组件,render函数会额外传入一个context参数用来表示上下文,即替代this。函数式组件没有实例,故不存在thisrender:function(createElement,context){ const anchor={props:{content:String,name:String},template:'<a :id="name" :href="`#${name}`"> {{content}}</a>'}const anchorEl=createElement(anchor,{props:{content:context.props.content, //通过context.props调用props传入的变量name:context.props.name}})const el=createElement(`h${context.props.level}`,[anchorEl])return el}
}
</script>

渲染函数 & JSX — Vue.js:更多关于函数式组件内容请看官网函数式组件

4.element-ui的el-row组件

最后以el-row组件的源码来分析,该源码的渲染逻辑在render函数上,非常简洁明了:

export default {name: 'ElRow',componentName: 'ElRow',props: {tag: {type: String,default: 'div'},gutter: Number,type: String,justify: {type: String,default: 'start'},align: {type: String,default: 'top'}},computed: {style() {const ret = {};if (this.gutter) {ret.marginLeft = `-${this.gutter / 2}px`;ret.marginRight = ret.marginLeft;}return ret;}},render(h) {return h(this.tag, {class: ['el-row',this.justify !== 'start' ? `is-justify-${this.justify}` : '',this.align !== 'top' ? `is-align-${this.align}` : '',{ 'el-row--flex': this.type === 'flex' }],style: this.style}, this.$slots.default);}
};

对着el-row组件传入参数的说明图来解释:

直接从render函数处进行分析,

1.传入第一个参数为this.tag,用于根据参数生成对应的html标签。

2.第二个参数中传入classstyle是根据props中的type,gutter,justify,align生成的。

3.第三个参数传入子节点。此处通过this.$slots.default拿到传入的子节点。例如:

<el-row><div>123</div>
</el-row>

此时,this.$slots.default 获取的数据则是一个包含上面<div>123</div>的VNode的数组。

以下内容来自官网:

拓展:slots() 和 children 对比

你可能想知道为什么同时需要 slots() childrenslots().default 不是和 children 类似的吗?在一些场景中,是这样——但如果是如下的带有子节点的函数式组件呢?

<my-functional-component><p v-slot:foo>first</p><p>second</p>
</my-functional-component>

对于这个组件,children 会给你两个段落标签,而 slots().default 只会传递第二个匿名段落标签,slots().foo 会传递第一个具名段落标签。同时拥有 children slots(),因此你可以选择让组件感知某个插槽机制,还是简单地通过传递 children,移交给其它组件去处理。

相关文章:

Vue | Vue深入浅出——Vue中的render函数详解

1.render函数 在编写vue单文件的大多数情况下&#xff0c;我们都是使用template模板来创建HTML。然而在一些条件判断比较复杂的场景下&#xff0c;使用JavaScript去描绘HTML的生成逻辑会显得更加的简洁直观。 使用Vue官网的例子来简单说明&#xff1a; 如果自己在开发的时候…...

数学基础 -- 线性代数之奇异值

奇异值与其应用 1. 奇异值定义 对于任意的矩阵 A A A&#xff08;可以是方阵或非方阵&#xff09;&#xff0c;存在三个矩阵 U U U、 Σ \Sigma Σ 和 V V V&#xff0c;使得&#xff1a; A U Σ V T A U \Sigma V^T AUΣVT 其中&#xff1a; U U U 是一个 m m m \ti…...

Python爬虫使用实例-wallpaper

1/ 排雷避坑 &#x1f95d; 中文乱码问题 print(requests.get(urlurl,headersheaders).text)出现中文乱码 原因分析&#xff1a; <meta charset"gbk" />解决方法&#xff1a; 法一&#xff1a; response requests.get(urlurl,headersheaders) response.en…...

探索Go语言中的随机数生成、矩阵运算与数独验证

1. Go中的随机数生成 在许多编程任务中&#xff0c;随机数的生成是不可或缺的。Go语言通过 math/rand 包提供了伪随机数生成方式。伪随机数由种子(seed)决定&#xff0c;如果种子相同&#xff0c;生成的数列也会相同。为了确保每次程序运行时产生不同的随机数&#xff0c;我们…...

无线安全(WiFi)

免责声明:本文仅做分享!!! 目录 WEP简介 WPA简介 安全类型 密钥交换 PMK PTK 4次握手 WPA攻击原理 网卡选购 攻击姿态 1-暴力破解 脚本工具 字典 2-Airgeddon 破解 3-KRACK漏洞 4-Rough AP 攻击 5-wifi钓鱼 6-wifite 其他 WEP简介 WEP是WiredEquivalentPri…...

牛客练习赛128:Cidoai的平均数对(背包dp)

题目描述 给定 nnn 对数 (ai,bi)(a_i,b_i)(ai​,bi​) 和参数 kkk&#xff0c;你需要选出一些对使得在满足 bib_ibi​ 的平均值不超过 kkk 的同时&#xff0c;aia_iai​ 的和最大&#xff0c;求出这个最大值。 输入描述: 第一行两个整数分别表示 n,kn,kn,k。 接下来 nnn 行&…...

Python世界:简易地址簿增删查改算法实践

Python世界&#xff1a;简易地址簿增删查改算法实践 任务背景编码思路代码实现本文小结 任务背景 该任务来自简明Python教程中迈出下一步一章的问题&#xff1a; 编写一款你自己的命令行地址簿程序&#xff0c; 你可以用它浏览、 添加、 编辑、 删除或搜索你的联系人&#xff…...

网络安全-intigriti-0422-XSS-Challenge Write-up

目录 一、环境 二、解题 2.1看源码 一、环境 Intigriti April Challenge 二、解题 要求&#xff1a;弹出域名就算成功 2.1看源码 我们看到marge方法&#xff0c;肯定是原型链污染题目 接的是传参&#xff0c;我们可控的点在于qs.config和qs.settings&#xff0c;这两个可…...

Debian Linux 11 使用crash

文章目录 前言一、环境安装1.1 安装debug package1.2 安装crash 二、使用crash 前言 # cat /etc/os-release PRETTY_NAME"Debian GNU/Linux 11 (bullseye)" NAME"Debian GNU/Linux" VERSION_ID"11" VERSION"11 (bullseye)" VERSION_C…...

python列表 — 按顺序找出b表中比a表多出的元素

目录 一、功能描述 二、适用场景 三、代码实现 一、功能描述 有a、b两个列表&#xff0c;a列表有3个元素&#xff1b;b列表有7个元素。b列表多出的一个元素可能在随机的位置&#xff0c;在不影响其他元素的情况下&#xff0c;找到b列表多出的那四个元素&#xff0c;并按照在…...

如何使用Python创建目录或文件路径列表

在 Python 中&#xff0c;创建目录或生成文件路径列表通常涉及使用 os、os.path 或 pathlib 模块。下面是一些常见的任务和方法&#xff0c;用于在 Python 中创建目录或获取文件路径列表。 问题背景 在初始阶段的 Python 学习过程中&#xff0c;可能遇到这样的问题&#xff1a…...

领夹麦克风哪个品牌好,哪种领夹麦性价比高,无线麦克风推荐

在音频录制需求日益多样化的今天&#xff0c;无线领夹麦克风作为提升音质的关键设备&#xff0c;其重要性不言而喻。市场上鱼龙混杂&#xff0c;假冒伪劣、以次充好的现象屡见不鲜。这些产品往往以低价吸引消费者&#xff0c;却在音质、稳定性、耐用性等方面大打折扣&#xff0…...

苍穹外卖学习笔记(五)

文章目录 二.新增菜品1.图片上传2.具体新增菜品 二.新增菜品 1.图片上传 这里采用了阿里云oss对象存储服务 application.yml alioss:endpoint: ${sky.alioss.endpoint}access-key-id: ${sky.alioss.access-key-id}access-key-secret: ${sky.alioss.access-key-secret}bucket…...

什么是卷积层、池化层、BN层,有什么作用?

什么是卷积层、池化层、BN层&#xff0c;有什么作用&#xff1f; 卷积层池化层BN层 卷积层 定义&#xff1a; 卷积层是CNN中的核心组件&#xff0c;它通过卷积运算对输入数据进行特征提取。卷积层由多个卷积单元组成&#xff0c;每个卷积单元的参数通过反向传播算法优化得到。…...

[学习笔记]《CSAPP》深入理解计算机系统 - Chapter 4 处理器体系结构Chapter 5 优化程序性能

总结一些第四章和第五章的一些关键信息 Chapter 4 处理器体系结构将处理组织成阶段 Chapter 5 优化程序性能 Chapter 4 处理器体系结构 在硬件中&#xff0c;寄存器直接将它的输入和输出线连接到电路的其他盆。 在机器级变成中&#xff0c;寄存器代表的是 CPU 中为数不多的可寻…...

案例分享|我是这样转型做数据产品经理的?

本文为才聚学员投稿的原创作品&#xff0c;现在才聚正面向专业项目管理者征集“项目管理实战案例”原创文章&#xff0c;被采纳即可获得丰厚稿酬&#xff0c;欢迎大家关注公众号踊跃投稿。 如您有意向投稿&#xff0c;可将稿件投递给我们。 故事介绍 三段故事&#xff0c;讲…...

ffmpeg面向对象-rtsp拉流相关对象

目录 1.AVFormatContext和FFFormatContext类。1.1 概述1.2 构造函数1.3 oopc的继承实现 2. AVInputFormat 类。2.1 多态的实现 3.所用设计模式3.1模板模式3.2 工厂模式&#xff1f; 3.3 rtsp拉流建链 4.this指针5.小结6.rtsp拉流流程 1.AVFormatContext和FFFormatContext类。 …...

feign client发送Post请求,发送对象参数,服务端接收不到正确参数报错排查

记一次feignclient发送请求服务端接收不到正确参数排查 服务端代码&#xff1a; Operation(summary "Create team")PostMapping("post")RequiresPermissions("team:add")public RestResponse addTeam(Valid Team team) {this.teamService.crea…...

Hadoop林子雨安装

文章目录 hadoop安装教程注意事项&#xff1a; hadoop安装教程 链接: 安装教程 注意事项&#xff1a; 可以先安装ububtu增强功能&#xff0c;完成共享粘贴板和共享文件夹 ubuntu增强功能 2.这里就可以使用共享文件夹 或者在虚拟机浏览器&#xff0c;用 微信文件传输助手 传文…...

Springboot项目总结

1.为了调用写在其他包里面的类的方法 但是不使用new来实现调用这个类里面的方法&#xff0c;这个时候我们就需要将这个类注入到ioc容器里面&#xff0c;通过ioc容器来实现自动生成一个对象。 对ioc容器的理解&#xff1a;自动将一个对象实现new. 考察了and 和 or组合使用&…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...