渲染函数render和函数式组件
渲染函数
- 当使用 DOM 内模板或 JavaScript 内的字符串模板时,模板会在运行时被编译为渲染函数。预编译模板最简单的方式就是使用单文件组件——相关的构建设置会自动把预编译处理好,所以构建好的代码已经包含了编译出来的渲染函数而不是原始的模板字符串。
- 渲染函数render参数createElement 接受的参数:
// @returns {VNode}
createElement(
// {String | Object | Function}
// 一个 HTML 标签字符串,组件选项对象(组件的参数),或者
// 解析上述任何一种的一个 async 异步函数。必需参数。
'div',
// {Object}
// 一个包含模板相关属性的数据对象
// 你可以在 template 中使用这些特性。可选参数。(当第一个参数是个组件配置对象时,第二个参数的部分key才有意义)
{
// (详情见下一节)
},
// {String | Array}
// 子虚拟节点 (VNodes),由 `createElement()` 构建而成,
// 也可以使用字符串来生成“文本虚拟节点”。可选参数。
[
'先写一些文字',
createElement('h1', '一则头条'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
- 参数1可是对象,是指可以是生成vue实例传入的对象。例如
import App from './App.vue'
...
render: h => h(App)
...
- 参数2Object包含如下,传入组件的各种值
{
// 和`v-bind:class`一样的 API
// 接收一个字符串、对象或字符串和对象组成的数组。
'class': {
foo: true,
bar: false
},
// 和`v-bind:style`一样的 API
// 接收一个字符串、对象或对象组成的数组。
style: {
color: 'red',
fontSize: '14px'
},
// 普通的 HTML 特性
attrs: {
id: 'foo'
},
// DOM 属性
// 属性和特性是不同的,特性指class等。
// 属性指元素节点自有特性,包括innerHTML(节点内容)、nodeName(节点名称,只读)、nodeValue(节点值,元素节点为null,文本节点为文本本身)、nodeType(节点类型)
// 节点包括多种:元素节点、属性节点(元素的特性也是个节点,例如:‘width:"30px"’)、文本节点、注释节点等
domProps: {
innerHTML: 'baz',
value: self.value // 对应的是nodeValue,在template中等同于<div>{{value}}</div>
},
// 事件监听器基于 `on`
// 所以不再支持如 `v-on:keyup.enter` 修饰器
// 需要手动匹配 keyCode。
on: {
click: this.clickHandler
},
// 如果组件是其他组件的子组件,需为插槽指定名称
slot: 'name-of-slot',
// 其他特殊顶层属性
key: 'myKey',
ref: 'myRef',
// 如果你在渲染函数中向多个元素都应用了相同的 ref 名,
// 那么 `$refs.myRef` 会变成一个数组。
refInFor: true
// 组件 props(只有对组件有效,设置传入组件props的数据)
props: {
myProp: 'bar'
},
// 仅用于组件,用于设置绑定到组件上的原生事件
nativeOn: {
click: this.nativeClickHandler
},
// 绑定到组件上的自定义指令。注意,你无法对 `binding` 中的 `oldValue`(设置传入组件的自定义指令)
// 赋值,因为 Vue 已经自动为你进行了同步。
directives: [
{
name: 'my-custom-directive',
value: '2',
expression: '1 + 1', // 字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg: 'foo', // 传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。(传入固定值)
modifiers: { // 一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
bar: true
}
}
],
// 作用域插槽格式(向组件的作用域插槽插入一个组件,slot-scope="props" )
// { name: props => VNode | Array<VNode> }
scopedSlots: {
default: props => createElement('span', props.text)
},
}
- 参数2内:v-model、v-if、v-for需要手动实现,v-model通过domProps.value和on.input实现
- 参数2内:对于 .passive、.capture 和 .once事件修饰符, Vue 提供了相应的前缀可以用于 on(其他的修饰符可以通过原生自带方法实现)
on: {
'!click': this.doThisInCapturingMode, // .capture(在捕获阶段执行)
'~keyup': this.doThisOnce, // .once
'~!mouseover': this.doThisOnceInCapturingMode, // .capture.once 或.once.capture
'&click':'this.doSome' // .passive(不阻止事件的默认行为,比如滚动事件,当监听滚动事件时不希望替换掉原有的滚动默认行为)
}
- 参数3(当参数2传入数组或对象时等同于参数3):组件树中的所有 VNodes 必须是唯一的。这意味着,下面的 render function 是无效的:
render: function (createElement) {
var myParagraphVNode = createElement('p', 'hi')
return createElement('div', [
// 错误-重复的 VNodes
myParagraphVNode, myParagraphVNode
])
}
//由于vnode是对象,需要使用工厂函数生成保持唯一性
render: function (createElement) {
return createElement('div',
Array.apply(null, { length: 20 }).map(function () { // Array.apply(null, { length: 20 })生成一个长度为20,每项都是null的数组
return createElement('p', 'hi')
})
)
}
$createElement
- 返回vnode工厂函数,和渲染函数render的参数createElement一样
const context = new Vue();
const h = context.$createElement;
函数式组件
- 函数式组件只能使用v-bind、v-on、slots插槽、inject注入数据
- 函数式组件只是一个函数,所以渲染开销也低很多(非函数式组件需要各种初始化所有渲染更慢点,并不是因为把模板转义成渲染函数的时间慢,这个过程已经在打包时完成了)。
- 然而,对持久化实例的缺乏也意味着函数式组件不会出现在 Vue devtools 的组件树里。(不会创建组件实例)
- 当你需要做这些时使用:(Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。)
- 程序化地在多个组件中选择一个
- 在将 children, props, data 传递给子组件之前操作它们。
- 函数式组件和使用渲染函数渲染的组件的区别在于
- 无状态 (没有响应式数据)(渲染函数render只运行一次不会根据数据变动而重新渲染)
- 无实例 (没有 this 上下文,函数式组件不能通过this.拿到传入的值,而是通过第二参数context获取。)
- 组件需要的一切都是通过上下文传递,context包括
- props:提供所有 prop 的对象
- children: VNode 子节点的数组(原来的this.$slots.default,实际包含了所有slots内的vnode,只是为了更方便获取全部slots)
- slots: 返回所有插槽的对象的函数(slots().default获取不具名插槽中传入的所有vnode)
- data:传递给组件的数据对象,作为 createElement 的第二个参数传入组件(自动整合为相同格式,不包括props)
- parent:对父组件的引用
- listeners: (2.3.0+) 一个包含了所有在父组件上注册的事件侦听器的对象。这只是一个指向 data.on 的别名。
- injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。
- 在 2.3.0 之前的版本中,如果一个函数式组件想要接受 props,则 props 选项是必须的。在 2.3.0 或以上的版本中,你可以省略 props 选项,所有组件上的特性都会被自动解析为 props。
- 在 2.5.0 及以上版本中,如果你使用了单文件组件,那么基于模板的函数式组件可以这样声明:可以省略 <script> 块中的 functional:true 选项。
// 作用域是context和正常模板的this相同,可以使用context中的所有属性或方法
<template functional>
<button
class="btn btn-primary"
v-bind="data.attrs"
v-on="listeners"
>
<slot/>
</button>
</template>
- 例子:可复用的过渡-函数组件
Vue.component('my-special-transition', {
functional: true,
render: function (createElement, context) {
var data = {
props: {
name: 'very-special-transition',
mode: 'out-in'
},
on: {
beforeEnter: function (el) {
// ...
},
afterEnter: function (el) {
// ...
}
}
}
return createElement('transition', data, context.children) // createElement函数返回的是一个vnode对象
}
})
渲染函数render和函数式组件的更多相关文章
- Vue.js 2.x render 渲染函数 & JSX
Vue.js 2.x render 渲染函数 & JSX Vue绝大多数情况下使用template创建 HTML.但是比如一些重复性比较高的场景,需要运用 JavaScript 的完全编程能力 ...
- Vue躬行记(7)——渲染函数和JSX
除了可通过模板创建HTML之外,Vue还提供了渲染函数和JSX,前者的编码自由度很高,后者对于开发过React的人来说会很熟悉.注意,Vue的模板最终都会被编译成渲染函数. 一.渲染函数 虽然在大部分 ...
- 基于VueJS的render渲染函数结合自定义组件打造一款非常强大的IView 的Table
基于VueJS的render渲染函数结合自定义组件打造一款非常强大的IView 的Table https://segmentfault.com/a/1190000015970367
- 理解Vue中的Render渲染函数
理解Vue中的Render渲染函数 VUE一般使用template来创建HTML,然后在有的时候,我们需要使用javascript来创建html,这时候我们需要使用render函数.比如如下我想要实现 ...
- Render渲染函数和JSX
1.Render函数:render是用来替换temlate的,需要更灵活的模板的写法的时候,用render. 官网API地址:https://cn.vuejs.org/v2/guide/render- ...
- Vue之render渲染函数和JSX的应用
一.模板缺陷 模板的最大特点是扩展难度大,不易扩展.可能会造成逻辑冗余 <Level :type="1">哈哈</Level> <Level :typ ...
- vue render 渲染函数
vue render 渲染函数 经常看到使用render渲染函数的示例,而且在一些特殊情况下,确实更好使用,可以更加有效地细分组件,因而借助vue-element-admin来学习一波 render函 ...
- vue入门:(底层渲染实现render函数、实例生命周期)
vue实例渲染的底层实现 vue实例生命周期 一.vue实例渲染的底层实现 1.1实例挂载 在vue中实例挂载有两种方法:第一种在实例化vue时以el属性实现,第二种是通过vue.$mount()方法 ...
- vue从入门到进阶:渲染函数 & JSX(八)
Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接 ...
随机推荐
- 重构 改善既有代码的设计 Replace Method with Method Object(以函数对象取代函数)
你有一个大型函数,其中对局部变量的使用使你无法采用Extract Method. 将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段.然后你可以在同一个对象中将这个大型函数分解为多个小型 ...
- js读取本地图片并显示
抄自 http://blog.csdn.net/qiulei_21/article/details/52785191 js读取本地图片并显示 第一种方法比较好 版权声明:本文为博主原创文章,未经博主允 ...
- NOIP2011提高组 选择客栈
原题 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖 ...
- Selenium·自动化基础
date:2018505+2018506 day05+06mor 一.安装环境 1.cmd→pip install selenium 2.将浏览器驱动放入X:\Python27下(如chromedri ...
- vue 安卓5.1 ios9 兼容性 白屏问题
// 针对安卓4.4/ios的兼容 import 'babel-polyfill' import Es6Promise from 'es6-promise' require('es6-promise' ...
- 关于http协议的一些笔记
1.正向代理和反向代理正向代理相当于客户端向代理发送服务器,代理将请求发给服务器,一般代理跟客户端有关系,没有查找的功能:反向代理作用于服务端,客户端向服务器代理发送请求,服务器代理去找需要的资源,然 ...
- 由一次报错引发的对于Spring创建对象的理解
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ent ...
- django中向用户发送邮件信息
发送邮件来让用户激活,因此,邮件中需要包含用户信息.但用户信息需要加密才可以.因此加密采用的是itsdangerous中的TimedJSONWebSignatureSerializer. 参考链接:h ...
- idea的maven项目下spring与mybatis整合
两周前学习mybatis框架,参考了网上多位大神的博客,但因为各种原因(不解释)总是没法成功搭建环境并运行项目.周末花了点时间阅读了文档并整理之前琐碎的内容,解决掉之前遇到的问题.现将整合环境的关键步 ...
- objdump和backtrace的配合使用
在程序调试过程中程序崩溃的情况时有发生,把出问题时的调用栈信息打印出来是一种不错的解决办法. 当然还有一些其他方法:https://www.cnblogs.com/jiangyibo/p/865372 ...