render函数使用和详解

news2025/2/26 22:59:55

背景

在平时编程时,大部分是通过template来创建html。但是在一些特殊的情况下,使用template方式时,就无法很好的满足需求,在这个时候就需要 通过JavaScript 的编程能力来进行操作。此时,就到了render函数展示拳脚去时候了。

render的作用

在官网的这里示例中,使用组件,将相同的内容通过solt放进h1-h6的标签中,在使用传统方式时,代码不仅冗长,而且在每一个级别的标题中重复书写了 ,在要插入锚点元素时还要再次重复。而使用render函数后,代码就精简了很多。

Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level,   // 标签名称
      this.$slots.default // 子节点数组
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

render函数的作用是,当场景中用 template 实现起来代码冗长繁琐而且有大量重复,这个时候使用就可以极大的简化代码。

render函数讲解

在使用render中,会使用到一个参数createElement,而这个createElement参数,本质上,也是一个函数,是vue中构建虚拟dom所使用的工具。下面就围绕着这个createElement来看一下。

createelement方法,有三个参数:

return createEement(, {}, [])
  1. 第一个参数: 是生成在页面上显示的标签元素(必需参数)
  2. 第二个参数: 是包含配置信息的数据对象(诸如HTML特性,属性,事件侦听器已经要绑定的classstyle)
  3. 第三个参数: 是一个子节点字符串或者包含子节点的数组.

注意:组件树中的所有vnode必须是唯一的
通过传入createElement参数,创建虚拟节点,然后再将节点返回给render返回出去。

总的来说,render函数的本质就是创建一个虚拟节点。
这里是 createElement 接受的参数:

// @returns {VNode}
createElement(
  // {String | Object | Function}
  // 一个 HTML 标签名、组件选项对象,或者
  // resolve 了上述任何一种的一个 async 函数。必填项。

  'div',

  // {Object}
  // 一个与模板中 attribute 对应的数据对象。可选。
  {
    style:'width:100px'
  },

  // {String | Array}
  // 子级虚拟节点 (VNodes),由 `createElement()` 构建而成,
  // 也可以使用字符串来生成“文本虚拟节点”。可选。
  [
    '先写一些文字',
    createElement('h1', '一则头条'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'
      }
    })
  ]
)

rendertemplate的区别

相同之处:
render 函数 跟 template 一样都是创建 html 模板

不同之处:

  • Template适合逻辑简单,render适合复杂逻辑。
  • 使用者template理解起来相对容易,但灵活性不足;自定义render函数灵活性高,但对使用者要求较高。
  • render的性能较高,template性能较低。
  • 使用render函数渲染没有编译过程,相当于使用者直接将代码给程序。所以,使用它对使用者要求高,且易出现错误
  • Render 函数的优先级要比template的级别要高,但是要注意的是Mustache(双花括号)语法就不能再次使用
    注意:template和render不能一起使用,否则无效

render举例

第一个参数{String | Object | Function}

第一个参数是一个必须的参数,这个参数可以是字符串string、对象object,或者一个函数function
比如我们想创建一个标签,以前的写法是这样的

<div id="app">
</div>
<script>
    //  实例
    const vm = new Vue({
        el: "#app",
        template:"<div></div>",
    })
</script>

或者在组件里面

<script>
export default {
    methods: {
    },
    render(h) {
        const cmp = {
            template: '<div></div>',
        }
        return h(cmp)
    }
}
</script>

或者

<script>
export default {
    methods: {
    },
    render(h) {
        return h('div')
    }
}
</script>

或者

这是最基本的用法

那么我们如何使用渲染函数来创建标签呢

字符串

第一个参数可以是标签名的字符串

<script>
export default {
    methods: {
    },
    render(h) {
        return h('div')
    }
}
</script>

或者

<div id="app">
</div>

<script>
    const vm = new Vue({
        el: "#app",
        render:function(createElement){
            return createElement("div")
        }
    })
</script>

createElement 传入了一个字符串参数div, 我们就会发现页面上div标签被渲染出来了

在这里插入图片描述

对象

参数除了是字符串外,可以是组件的选项对象

<div id="app"></div>

<script>
    //  组件选项对象
    let MyComponent = {
        template:"<h3>我就一个组件而已</h3>",
    };

    //  实例中注册组件
    const vm = new Vue({
        el: "#app",
        render(createElement){
            return createElement(MyComponent)
        }
    })

</script>

或者

<script>
export default {
    methods: {
    },
    render(h) {
        let MyComponent = {
        template:"<h3>我就一个组件而已</h3>",
    };
        return h(MyComponent)
    }
}
</script>

然后引入使用

<template>
  <div id="app">
    <CustomPop/>
  </div>
</template>

<script>

import CustomPop from './components/CustomPop.vue'

export default {
  name: 'App',
  components: {
    CustomPop
  }
}

我们发现会直接显示组件的内容
在这里插入图片描述

若遇到以下错误信息

You are using the runtime-only build of Vue where the template compiler is not available

请参考这篇博客的解决办法
https://blog.csdn.net/qq_44732146/article/details/132767730

函数

其实第一个参数也可以是一个函数,只不过这个函数执行完毕后,需要返回一个标签名的字符串或者组件对象

<div id="app"></div>

<script>
    //  实例中注册组件
    const vm = new Vue({
        el: "#app",
        render(createElement){
            let eleFn = function(){
                return {
                    template:"<div>Hello Vue!</div>"
                }
            }
            return createElement(eleFn())
        }
    })

</script>

或者以组件的方式

<script>
export default {
    methods: {
    },
    render(h) {
        let eleFn = () => {
            return { template: "<div>Hello Vue!</div>" }
        };
        return h(eleFn())
    }
}
</script>

显示结果在这里插入图片描述

第二个参数:{Object}

是一个可选参数,这个参数是一个Object。关于第一个参数创建的 标签的属性

{
  // 与 `v-bind:class` 的 API 相同,
  // 接受一个字符串、对象或字符串和对象组成的数组
  'class': {
    foo: true,
    bar: false
  },
  // 与 `v-bind:style` 的 API 相同,
  // 接受一个字符串、对象,或对象组成的数组
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 普通的 HTML attribute
  attrs: {
    id: 'foo'
  },
  // 组件 prop
  props: {
    myProp: 'bar'
  },
  // DOM property
  domProps: {
    innerHTML: 'baz'
  },
  // 事件监听器在 `on` 内,
  // 但不再支持如 `v-on:keyup.enter` 这样的修饰器。
  // 需要在处理函数中手动检查 keyCode。
  on: {
    click: this.clickHandler
  },
  // 仅用于组件,用于监听原生事件,而不是组件内部使用
  // `vm.$emit` 触发的事件。
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
  // 赋值,因为 Vue 已经自动为你进行了同步。
  directives: [
    {
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }
  ],
  // 作用域插槽的格式为
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props => createElement('span', props.text)
  },
  // 如果组件是其它组件的子组件,需为插槽指定名称
  slot: 'name-of-slot',
  // 其它特殊顶层 property
  key: 'myKey',
  ref: 'myRef',
  // 如果你在渲染函数中给多个元素都应用了相同的 ref 名,
  // 那么 `$refs.myRef` 会变成一个数组。
  refInFor: true
}

//  class style的不同写法
{
    class:["class1",{"class2":true}]style: {background: red}
}

请注意,class,style并没有在attrs属性中,他们是单独设置的,这是因为v-bind指令的特性,如果仅仅将class或者style设置在attrs对象中的一个属性,就不能将class和style设置为数组或是对象了。
举例:

const vm = new Vue({
    el: "#app",
    render: function (createElement) {

        // 第一个参数是一个简单的HTML标签字符 “必选”
        // 第二个参数是一个包含模板相关属性的数据对象 “可选”
        return createElement('div', {
            'class': {
                foo: true,
                bar: false
            },
            style: {
                color: 'skyblue',
                fontSize: '24px'
            },
            attrs: {
                id: 'foo'
            },
            domProps: {
                innerHTML: 'Hello Vue!'
            }
        })
    }
})

最终生成的DOM,将会带一些属性和内容的div元素,如下图所示:
在这里插入图片描述

第三个参数: {String | Array}

这个参数是可选的,可以给其传一个StringArray处理子节点

字符串

当第三个参数为字符串是,就是节点的文本内容

<script>
    const vm = new Vue({
        el: "#app",
        render:function(createElement){
            return createElement("input", {
                class:"title"
            },"这是标题")
        }
    })
</script>

或者组件的方式

<script>
export default {
    methods: {
    },
    render(h) {
        return h("div", {
            class: "title"
        }, "这是标题")
    }
}
</script>

导入该组件就可以使用了

显示结果:

在这里插入图片描述

数组

数组中可以放多个节点,可以说是字符串的文本节点, 也可以是通过createElement或者render创建创建的节点

<script>
    const vm = new Vue({
        el: "#app",
        render(h){
            return h("div",{
                class:"box",
            },[
                h("span","我是一个span标签"),
                h("input",{
                    attrs:{
                        type:"button",
                        value:"按钮"
                    }
                })
            ])
        }
    })
</script>

组件的方式

<script>
export default {
    methods: {
    },
    render(h) {
        return h("div", {
            class: "box",
        }, [
            h("span", "我是一个span标签"),
            h("input", {
                attrs: {
                    type: "button",
                    value: "按钮"   
                }
            })
        ])
    }
}
</script>

显示结果:
在这里插入图片描述

渲染函数简写

我们会发现每次写createElement会非常繁琐,所以我们可以给这个函数定义别名h

那么我们的代码就可以修改为

<div id="app"></div>

<script>
    const vm = new Vue({
        el: "#app",
        render(h){
            return h("input", {
                class:"title"
            },["这是标题"])
        }
    })
</script>

约束:

约束的理解

组件树中的所有虚拟DOM(VNode)必须是唯一的,

例如,我想通过render函数实现下面的效果
在这里插入图片描述

你可能想到的简单方式

<div id="app">
</div>

<script>
    //  实例中注册组件
    const vm = new Vue({
        el:"#app",
        data:{
            msg:'hello'
        },
        render(h){
            // 1\. 创建虚拟DOM 节点
            let myVNode = h("p","hello");

            // 2\. 返回最终的虚拟DOM
            return h("div",[
                myVNode,myVNode,myVNode,myVNode
            ])
        }
    })
</script>

在这里插入图片描述
我们会发现虽然可以实现效果, 也没有报错,但是不合法

那么我们应该如何实现呢

建议使用的方法

使用数据map帮我们处理创建多个虚拟DOM

示例:

<script>
    const vm = new Vue({
        el:"#app",
        data:{
            msg:'hello'
        },
        render(h){
            // 返回最终的虚拟DOM
            return h("div",
                     Array.apply(null,{length:4}).map(() => {
                        return h("p","hello")
                    })
             )
        }
    })
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/990569.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】迭代器__iter__、__next__

这里主要纠正迭代器的用法&#xff0c;因为一些教程传播错误示例让我很无语。 最大的错误就是&#xff0c;把__iter__和__next写在同个类里&#xff0c;每每看见都感到诧异。不是说这方法不行&#xff0c;主要是&#xff0c;一旦出现预期之外的运行结果往往很难查到原因(因为它…

Nomad 系列-Nomad+Traefik+Tailscale 集成实现零信任安全

系列文章 Nomad 系列文章Traefik 系列文章Tailscale 系列文章 概述 终于到了令人启动的环节了&#xff1a;NomadTraefikTailscale 集成实现零信任安全。 在这里&#xff1a; Nomad 负责容器调度&#xff1b;&#xff08;容器编排工具&#xff09;Traefik 负责入口流量&…

文件导入之Validation校验List对象数组

背景&#xff1a; 我们的接口是一个List对象&#xff0c;对象里面的数据基本都有一些基础数据校验的注解&#xff0c;我们怎么样才能校验这些基础规则呢&#xff1f; 我们在导入excel文件进行数据录入的时候&#xff0c;数据录入也有基础的校验规则&#xff0c;这个时候我们又…

Linux下C语言使用 netlink sockets与内核模块通信

netlink简介 Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。在Linux标准内核中&#xff0c;系统默认集成了很多netlink实例&#xff0c;比如日志上报、路由系统等&#xff0c;netlink消息是双向的&a…

解决 tesserocr报错 Failed to init API, possibly an invalid tessdata path : ./

问题描述 我们在初次使用tesserocr库的时候&#xff0c;可能会报以下错误&#xff1a; RuntimeError: Failed to init API, possibly an invalid tessdata path: ./ 这是因为我们在使用 conda 创建的环境中找不到"tessdata"这个文件夹。 解决办法 这时候把Tessera…

【CMake工具】工具CMake编译轻度使用(C/C++)

目录 CMake编译工具 一、CMake概述 二、CMake的使用 2.1 注释 2.1.1 注释行 2.1.2 注释块 2.2 源文件 2.1.1 共处一室 2.1.2 VIP包房 2.3 私人定制 2.2.1 定义变量 2.2.2 指定使用的C标准 2.2.3 指定输出的路径 2.4 搜索文件 2.3.1 方式1 2.3.2 方式2 2.5 包含…

CRM软件系统能否监控手机的使用

CRM可以监控手机吗&#xff1f;答案是不可以。CRM是一款帮助企业优化业务流程&#xff0c;提高销售效率的工具。例如Zoho CRM&#xff0c;最多也就是听一下销售的通话录音&#xff0c;却不可以监控手机&#xff0c;毕竟CRM不是一款监控软件。 CRM的主要作用有以下几点&#xf…

CASAIM与南京航空航天大学在自动化叶片曲面分析系统开展合作,推动航空航天发动机零部件自动化3D检测进程

近期&#xff0c;CASAIM与南京航空航天大学在自动化叶片曲面分析系统展开深入合作&#xff0c;充分发挥双方在航空航天和智能检测领域优势&#xff0c;共同推动航空航天发动机零部件自动化3D检测进程。 南京航空航天大学创建于1952年10月&#xff0c;是新中国自己创办的第一批…

聚观早报|华为Mate 60 Pro支持面容支付;特斯拉重回底特律车展

【聚观365】9月8日消息 华为Mate 60 Pro已支持面容支付 特斯拉将重回底特律车展 iPhone在美国有1.67亿用户 韩国半导体8月份出口85.6亿美元 比亚迪元PLUS冠军版将于9月15日上市 华为Mate 60 Pro已支持面容支付 毫无预热的华为Mate 60 Pro突然在华为商城首批开售&#xf…

Ansys Zemax | 手机镜头设计 - 第 3 部分:使用 STAR 模块和 ZOS-API 进行 STOP 分析

本文是 3 篇系列文章的一部分&#xff0c;该系列文章将讨论智能手机镜头模组设计的挑战&#xff0c;从概念、设计到制造和结构变形的分析。本文是三部分系列的第三部分。它涵盖了使用 Ansys Zemax OpticStudio Enterprise 版本提供的 STAR 技术对智能手机镜头进行自动的结构、热…

微信小程序的开发---tabBar的介绍

目录 一、tabBar的介绍 二、tabBar的6个组成部分 三、tabBar节点的配置项 四、tab项的配置选项 五、tabBar的使用 一、tabBar的介绍 tabBar是移动端应用常见的页面效果&#xff0c;用于实现多页面的快速切换。小程序中通常将其分为&#xff1a; &#xff08;1&#xff09;…

猫头虎解析:如何巧妙避免GET请求中的“EOF“错误?

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

企业架构LNMP学习笔记22

防盗链原理和实现。 域名A的资源文件&#xff0c;经常被域名B直接调用访问。 而用户经常访问域名B&#xff0c;看到的资源&#xff08;图片等&#xff09;以为是域名B的&#xff0c;实际则是域名A的。 但是域名A没有获得任何收益&#xff0c;却要给域名B来源的访问消耗服务器…

解决eclipse的报错:Must declare a named package because this compilation

刚安装完成eclipse&#xff0c; 创建类的时候报错 报错信息如下&#xff1a; 原因&#xff1a;新版本的ECLIPSE要求每一个类都必须定义在包里面 解决方法&#xff1a;创建类的时候指定类的名字&#xff0c;如下图&#xff1a;Package 里面填写ch3&#xff0c;表示包名 创建完成…

智慧物联网医疗,树立可持续性智能化和便利化新标杆

医疗物联网&#xff08;IoMT&#xff09;是一个快速发展的领域&#xff0c;它正在改变医疗保健的未来。IoMT 指的是物理设备、车辆、家用电器和其他嵌入传感器、软件和网络连接的对象的网络。这些设备可以帮助医疗保健提供者更好地了解患者的状况&#xff0c;并提供更高效和更有…

区分何时使用内连接或者外连接

一张表(A)中的一条记录可以对应另一张表(B)中的多条记录; 另一张表(B)中的一条记录只能对应一张表(A)中的一条记录。 //查询所有姓张的学生的id,name和所在班级name 这里如果外键可以为空的话就需要使用左外连接&#xff0c;才可以查到。 内连接 //假如外键不可以为空select…

Canape使用中遇到问题的解决办法

问题一、canape绘制目标时&#xff0c;二维结构体变量只能录制16个的解决办法 打开ASAP2 Studio 2.6 -Expert 软件。 把该软件中的设置项如下图进行修改。 然后用ASAP2 Studio 2.6 -Expert 软件 打开elf文件导出成A2L文件。 最后关闭该软件。 再在canape工程中重新加载刚才…

1.8 工程相关解析(各种文件,资源访问

目录 1.8 工程相关解析(各种文件&#xff0c;资源访问) 分类 Android 基础入门教程 本节引言&#xff1a; 1.工程项目结构解析&#xff1a; 1.res资源文件夹介绍&#xff1a; 2.如何去使用这些资源 2.深入了解三个文件&#xff1a; MainActivity.java&#xff1a; 布局…

指针-成绩统计

任务描述 请设计一个函数&#xff0c;以指针变量作为函数的参数&#xff0c;从标准输入上读入数量不定的成绩。统计全班成绩的总数量、90 分及以上成绩的个数、60 分及以上成绩的个数和全班成绩的平均分&#xff0c;并返回这四个数给主程序。编写主程序调用此函数完成统计功能…

gitlab 点击Integrations出现500错误

背景&#xff1a;在新服务器重新搭建了gitlab&#xff0c;并导入原来gitlab的备份&#xff0c;在项目中点击点击Integrations出现500错误。 解决方法&#xff1a;1.进入新服务器&#xff0c;将 /etc/gitlab/gitlab-secrets.json重命名为 /etc/gitlab/gitlab-secrets.json.bak …