Vue.js 2.x render 渲染函数 JSX
Vue.js 2.x render
渲染函数 & JSX
Vue绝大多数情况下使用template
创建 HTML。但是比如一些重复性比较高的场景,需要运用 JavaScript 的完全编程能力,可以使用render
函数。
1. 节点、树以及虚拟DOM
每个元素都是一个节点。每片文字也是一个节点。甚至注释也都是节点。
一个节点就是页面的一个部分。每个节点都可以有子节点。
比如上面的节点树就表示下面的代码:
<div><h1>My title</h1>Some text content<!-- TODO: 添加标签行 -->
</div>
1.1 虚拟 DOM
Vue 通过建立一个虚拟 DOM 对真实 DOM 发生的变化保持追踪。
虚拟 DOM 是对Vue组件树建立起来的整个 VNode(Virtual Node)树的称呼。
1.1.1 createElement 参数
// @returns {VNode}
createElement(// {String | Object | Function}// 一个 HTML 标签字符串,组件选项对象,或者// 解析上述任何一种的一个 async 异步函数// 必须参数'div',// {Object}// 一个包含模板相关属性的数据对象// 你可以在 template 中使用这些特性// 可选参数{ // 属性参见 1.1.2 深入 data 对象},// {String | Array}// 子虚拟节点(VNodes) 由 createElement() 构建而成// 也可以使用字符串来生成“文本虚拟节点”// 可选参数['文字',createElement('h1', '一个标题'),createElement(MyComponent, {props: {someProp: 'foo'}})]
)
1.1.2 深入 data 对象
在 VNode 数据对象中,下列属性名是级别最高的字段。该对象也允许绑定普通的 HTML 特性,就像 DOM 属性一样,比如innerHTML
(这会取代v-html
指令)。
{// 和 v-bind:calss 一样的API// 接收一个字符串、对象或字符串和对象组成的数组'class': {foo: true,bar: false},// 和 v-bind:style 一样的API// 接收一个字符串、对象或对象组成的数组style: {color: 'red',fontSize: '14px'},// 普通的 HTML 特性attrs: {id: 'foo'},// 组件的 propsprops: {myProp: 'bar'},// DOM属性domProps: {innerHTML: 'baz'},// 事件监听器基于 on// 所以不再支持如 v-on:keyup.enter 修饰器// 需要手动匹配 keyCodeon: {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',// 其他特殊顶层属性key: 'myKey',ref: 'myRef',// 如果在渲染函数中向多个元素都应用了相同的 ref 名// 那么 $refs.myRef 会变成一个数组refInfor: true
}
1.1.3 完整示例
一个生成锚点标题的组件:
var getChildrenTextContent = function (children) {return children.map(function (node) {return node.children? getChildrenTextContent(node.children): node.text}).join('')
}Vue.component('anchored-heading', {render: function (createElement) {// 创建 kebab-case 风格的IDvar headingId = getChildrenTextContent(this.$slots.default).toLowerCase().replace(/\W+/g, '-').replace(/(^-|-$)/g, '')return createElement('h' + this.level,[createElement('a', {attrs: {name: headingId,href: '#' + headingId}}, this.$slots.default)])},props: {level: {type: Number,required: true}}
})
使用效果:
<div id="app"><anchored-heading :level="1">first</anchored-heading><anchored-heading :level="2">second</anchored-heading><anchored-heading :level="3">third<small>thirdSub</small></anchored-heading>
</div>
1.1.4 约束
组件树中的所有 VNodes 必须是唯一的。
比如这样写是错误的:
render: function (createElement) {var myParagraphVNode = createElement('p', 'hi')return createElement('div', [// 错误-重复的 VNodesmyParagraphVNode, myParagraphVNode])
}
如果需要重复多次元素/组件,可以用工厂函数来实现:
render: function(createElement) {return createElement('div',Array.apply(null, { length: 20 }.map(function() {return createElement('p', 'hello')})));
}
1.2 使用 JavaScript 代替模板功能
1.2.1 v-if 和 v-for
只要在原生的 JavaScript 中可以轻松完成的操作,Vue的render函数就不会提供专有的替代方法。
比如这里的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 方法重写:
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 here.');}
}
1.2.2 v-model
render 函数中没有与 v-model
直接对应的方法,需要手动实现:
props: ['value'],
render: function (createElement) {var self = this;return createElement('input', {// DOM属性domProps: {value: self.value},on: {input: function(e) {self.$emit('input', e.target.value);}}})
}
1.3 事件&按键修饰符
对于.passive
、.capture
、.once
事件修饰符,Vue提供了相应的前缀可以用于on
:
Modifier(s) | Prefix |
---|---|
.passive
|
&
|
.capture
|
!
|
.once
|
~
|
.capture.once 或.once.capture
|
~!
|
比如:
on: {'!click': this.doThisInCapturingMode,'~keyup': this.doThisOnce,'~!mouseover': this.doThisOnceInCapturingMode
}
对于其他的修饰符,可以在事件处理函数中使用事件方法:
Modifier(s) | Equivalent in Handler |
---|---|
.stop
|
e.stopPropagation()
|
.prevent
|
e.preventDefault()
|
.self
|
if (e.target !== e.currentTarget) return;
|
.enter , .13
|
e.keyCode === 13
|
比如:
on: {keyup: function (event) {// 如果触发事件的元素不是事件绑定的元素// 则返回if (event.target !== event.currentTarget) return// 如果按下去的不是 enter 键或者// 没有同时按下 shift 键// 则返回if (!event.shiftKey || event.keyCode !== 13) return// 阻止 事件冒泡event.stopPropagation()// 阻止该元素默认的 keyup 事件event.preventDefault()// ...}
}
1.4 插槽
可以通过this.$slots
访问静态插槽内容,得到的是一个 VNodes 数组:
render: function(createElement) {// `<div><slot></slot></div>`return createElement('div', this.$slots.default)
}
也可以通过this.$scopeSlots
访问作用域插槽,得到的是一个 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', {// 在数据对象中传递 scopedSlots// 格式:{ name: props => VNode | Array<VNode> }scopedSlots: {default: function(props) {return createElement('span', props.text)}}})])
}
2. JSX
在Vue中使用JSX语法,可以避免书写繁杂冗余的render代码,Babel插件用于在Vue中使用JSX语法。
使用文档
import AnchoredHeading from './AnchoredHeading.vue'new Vue({el: '#app',render: function(h) {return (<AnchoredHeading level={1}><span>Hello</span> world</AnchoredHeading>)}
})
3. 函数式组件
一个函数是组件,意味着它是无状态(没有响应式数据),无实例(没有this上下文)的:
Vue.component('my-component', {functional: true,// props可选 v2.3.0^props: {},// 为了弥补缺少的实例// 提供第二个参数作为上下文render(createElement, context) {}
})
在v2.5.0^版本中,单文件组件基于模板的函数式组件可以这样声明:
<template functional></template>
组件需要的一切都是通过上下文来传递:
props
提供所有prop对象children
VNode子节点的数组slots
返回所有插槽的对象的函数scopedSlots
一个暴露传入的作用域插槽以及函数形式的普通插槽的对象data
传递给组件的数据对象,作为CreateElement的第二个参数传入组件parent
对父组件的引用listeners
一个包含了所有在父组件上注册的事件侦听器的对象,data.on
的别名injections
如果使用了inject选项,该对象包含了应当被注入的属性
之前的锚点标题组件可以改为如下的函数式组件:
...Vue.component('anchored-heading', {functional: true,render: function (createElement, context) {// 创建 kebab-case 风格的IDvar headingId = getChildrenTextContent(context.children).toLowerCase().replace(/\W+/g, '-').replace(/(^-|-$)/g, '')return createElement('h' + context.props.level,[createElement('a', {attrs: {name: headingId,href: '#' + headingId}}, context.children)])},props: {level: {type: Number,required: true}}
})
3.1 想子组件或子元素传递特性和事件
在普通组件中,没有被定义为 prop 的特性会自动添加到组件的根元素上,将现有的同名特性替换或智能合并。
而函数式组件要求必须显示定义该行为:
Vue.component('my-functional-button', {functional: true,render: function(createElement, context) {return createElement('button', context.data, context.children)}
})
如果使用模板的函数式组件,还需要手动添加特性和监听器。
<template functional><buttonclass="btn btn-primary"v-bind="data.attrs"v-on="listeners"><slot/></button>
</template>
3.2 slots()和children对比
slots()和children对比
总的来说个人理解,slots()
可以拿到具名插槽,children
拿到所有。
4. 模板编译
模板编译
The end
2019-8-13 15:45:59
转载于:https://www.cnblogs.com/jehorn/p/11346358.html
Vue.js 2.x render 渲染函数 JSX相关推荐
- vue 渲染函数处理slot_vue render 渲染函数
vue render 渲染函数 经常看到使用render渲染函数的示例,而且在一些特殊情况下,确实更好使用,可以更加有效地细分组件,因而借助vue-element-admin来学习一波 render函 ...
- Vue render渲染函数
这里写自定义目录标题 Vue render渲染函数 基础 render渲染函数的作用 render函数讲解 render和template的区别 render举例 Vue render渲染函数 基础 ...
- vue3.0中使用render渲染函数渲染组件或标签
使用 render 渲染函数是使用了 js 来渲染组件或标签 而我们平时使用时是直接在 template 标签中直接书写 这两种方法都可以实现组件或标签的创建 下面是使用 render 渲染的方法 i ...
- 二次封装Element Ui的Table中使用render渲染函数
render函数的使用 render在element UI中的使用 render函数是什么 具体参数用法 render在element UI中的使用 {prop: 'button',label: '操 ...
- iview table 自定义列_基于VueJS的render渲染函数打造一款非常强大的IView 的Table组件...
1.render渲染函数的介绍 字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力.该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode. 如果组 ...
- 【前端基础知识】最基础的render渲染函数知识,一看就会
Vue-Render渲染函数 是什么? 如何使用? 1. createElement的第一个参数 1.1 HTML 标签名(可以动态创建标签) 1.2 组件 2. createElement的第二个参 ...
- 【vue3】vue3在setup的render渲染函数中如何使用slots(插槽)?
在setup中使用插槽,需要配合render渲染函数,先上代码. 子组件slotsTest.vue: <script lang="ts"> import { h,ren ...
- 浅析Vue.js 中的条件渲染指令
1 应用于单个元素 Vue.js 中的条件渲染指令可以根据表达式的值,来决定在 DOM 中是渲染还是销毁元素或组件. html: <div id="app"> < ...
- Vue 中的 Render 全面详解 (渲染函数 JSX)
相信大家都或多或少的在 code 中见过 或使用过 Render,如果你对它还是一脸懵逼,那就快上车!今天就带你来盘它.附 Element 表格自定义全选示例. 文章目录 一.Render 的资料简介 ...
最新文章
- 配置CACTI监控MySQL数据库状态(1)准备工作
- linux环境双网卡主机路由配置
- 【转】 (C#)利用Aspose.Cells组件导入导出excel文件
- configure: error: Curl library not foun
- 如何监听RecyclerView划到最后一条数据
- C++ const vector的迭代器
- 从零开始学Pytorch(十)之循环神经网络基础
- 数据结构与算法之链式栈
- zed相机拆机_轻松实现位置追踪,Stereolabs推出二代ZED相机
- 单片机相关知识点,最强科普总结!
- 求助fax4j,发送和接收传真
- 网络带宽压力测试教程
- 找回git误删除的文件
- android手机和包支付,中国移动和包支付客户端下载-和包支付appv9.7.16 安卓版-腾牛安卓网...
- java颜色识别_Java颜色检测
- 天猫精灵使用体验之一——天猫精灵初体验
- Mac电脑 zsh: command not found: vue
- 营改增后计算机维修费税率,2020国税维修费税率是多少?
- python print空格占位_python的占位格式符 %
- 卸载删除JDK(详细步骤)