vue之render基本书写方法
Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器。
render 基本写法
export default {
name: 'renderTest',
data() {},
render: (createElement) => {
return createElement(tag, data, context)
},
props: {},
methods: {},
created () {}
...
}
Vue 通过建立一个虚拟 DOM 对真实 DOM 发生的变化保持追踪。
render函数提供了一个参数createElement(可以简写为h), 用来生成DOM, 其有三个参数:
- 第一个参数: {String | Object | Function}, 必要参数,一个 HTML 标签字符串,组件选项对象,或者一个返回值类型为 String/Object 的函数
- 第二个参数: {Object},可选参数,一个包含模板相关属性的数据对象,这样,您可以在 template 中使用这些属性。
- 第三个参数: {String | Array},可选参数, 子节点 (VNodes),由
createElement()构建而成, 或使用字符串来生成“文本节点”。
数据对象详解
{
// 和`v-bind:class`一样的 API
'class': {
foo: true,
bar: false
},
// 和`v-bind:style`一样的 API
style: {
color: 'red',
fontSize: '14px'
},
// 正常的 HTML 特性
attrs: {
id: 'foo'
},
// 组件 props
props: {
myProp: 'bar'
},
// DOM 属性
domProps: {
innerHTML: 'baz'
},
// 事件监听器基于 `on`
// 所以不再支持如 `v-on:keyup.enter` 修饰器
// 需要手动匹配 keyCode。
on: {
click: this.clickHandler
},
// 仅对于组件,用于监听原生事件,而不是组件内部使用 `vm.$emit` 触发的事件。
nativeOn: {
click: this.nativeClickHandler
},
// 自定义指令。注意,您无法对绑定中的 `oldValue` 赋值
// Vue 会为您持续追踪
directives: [
{
name: 'my-custom-directive',
value: '2',
expression: '1 + 1',
arg: 'foo',
modifiers: {
bar: true
}
}
],
// Scoped slots in the form of
// { name: props => VNode | Array<VNode> }
scopedSlots: {
default: props => createElement('span', props.text)
},
// 如果组件是其他组件的子组件,需为插槽指定名称
slot: 'name-of-slot',
// 其他特殊顶层属性
key: 'myKey',
ref: 'myRef'
}
v-if 、 v-for 与 v-model
render 函数中没有与v-if 、 v-for 、v-model 相应的 api, 必须自己来实现相应的逻辑
render: function (createElement) {
if (this.items.length) {
return createElement('ul', this.items.map(function (item) {
return createElement('li', item)
}))
} else {
return createElement('p', 'No items found.')
}
}
完整示例
renderTest组件
export default {
name: 'renderTest',
data() {
return {
}
},
render: function (createElement) {
return createElement(
'h' + this.level,
{
on: {
click: this.clickHandler
}
},
[
createElement('a', {
attrs: {
href: '##'
}
}, this.$slots.default)
]
)
},
props: {
level: {
type: Number,
required: true
}
},
methods: {
clickHandler () {}
}
}
使用组件
<renderTest :level="1">
<button> Hello world!</button>
</renderTest>
组件中自定义render(函数式组件)
render组件
export default {
name: 'renderTest',
functional: true,
props: {
render: Function,
item: String,
index: Number
},
render: (h, ctx) => {
const params = {
item: ctx.props.item,
index: ctx.props.index
}
return ctx.props.render(h, params)
}
}
我们将组件记为 functional,这意味它无状态(没有 data),无实例(没有 this 上下文)。
在添加 functional: true 之后,组件的 render 函数之间将增加 ctx 参数
组件需要的一切都是通过 ctx 传递,包括:
- props: 提供 props 的对象
- children: VNode 子节点的数组
- slots: slots 对象
- data: 传递给组件的 data 对象
- parent: 对父组件的引用
list组件
<template>
<ul class="bs-list left" style="width:200px;">
<li v-for="(item, i) in listDate" class="list-item" :key="i">
<span>{{item}}</span>
<renderTest v-if="renderfun" :item="item" :index="i" :render="renderfun"></renderTest>
</li>
</ul>
</template>
<script>
import renderTest from './renderTest.js'
export default {
name: 'lists',
components: { renderTest },
props: {
listDate: {
type: Array
},
renderfun: {
type: Function,
default() {
return () => false
}
}
}
}
</script>
使用组件
<template>
<div class="text">
<lists :listDate="listDate" :renderfun="renderfun"></lists>
</div>
</template>
<script>
import lists from './lists.vue'
export default {
name: 'text',
components: { lists },
data() {
return {
listDate: [ 'list item 1', 'list item 2', 'list item 3', 'list item 4', 'list item 5' ],
renderfun: (h, ctx) => {
return h('div', {
style: {display: 'inline-block', float: 'right'}
}, [
h('button', {
class: ['btn-primary'],
on: {
click: () => {
this.listDate.splice(ctx.index, 1)
}
}
}, '删除')
])
}
}
}
}
</script>
JSX使用
安装babel依赖
npm install babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props babel-preset-env --save-dev
.babelrc 文件配置
{
"presets": ["env"],
"plugins": ["transform-vue-jsx"]
}
书写格式
render (h) {
return (
<div
// 普通的属性
id="foo"
// DOM 属性,添加前缀`domProps`
domPropsInnerHTML="bar"
// 事件监听,添加前缀 `on` or `nativeOn`
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
// 其他属性
class={{ foo: true, bar: false }}
style={{ color: 'red', fontSize: '14px' }}
key="key"
ref="ref"
slot="slot">
</div>
)
}
实例
export default {
name: 'renderJSX',
data() {
return {
num: 1
}
},
render() {
const data = {
class: ['b', 'c']
}
return (<div class = 'div'>
<span>123</span>
<button onClick={this.clickHandler} class='btn-primary'>btn</button>
<span class='a' {...data}>{this.num}</span>
</div>)
},
props: {
level: {
type: Number
}
},
methods: {
clickHandler() {
this.num++
console.log('clickHandler')
}
},
created() {}
}
https://vuefe.cn/v2/guide/render-function.html
https://github.com/vuejs/babel-plugin-transform-vue-jsx
vue之render基本书写方法的更多相关文章
- Vue2.x源码学习笔记-Vue实例的属性和方法整理
还是先从浏览器直观的感受下实例属性和方法. 实例属性: 对应解释如下: vm._uid // 自增的id vm._isVue // 标示是vue对象,避免被observe vm._renderProx ...
- 关于Vue的Render的讲解
首先我们传统的对于DOM的操作基本上都是通过js直接的获取一个节点,然后对DOM进行增加或者是删除.而Vue的Render这个函数是通过js虚拟的添加dom节点,然后虚拟的添加到html节点上去. 算 ...
- vue插件开发的两种方法:以通知插件toastr为例
方法一: 1.写插件: 在 src 文件夹下面建 lib 文件夹用于存放插件,lib 文件夹下再建toastr文件夹,在toastr文件夹下新建 toastr.js 和 toastr.vue两个文件. ...
- Vue(十二)vue实例的属性和方法
vue实例的属性和方法 1. 属性 vm.$el vm.$data vm.$options vm.$refs <!DOCTYPE html> <html lang="en& ...
- 在Vue中关闭Eslint 的方法
在vue项目中关闭ESLint方法:找到 webpack.base.conf.js 将这些代码注释掉, { test: /\.(js|vue)$/, loader: 'eslint-loader', ...
- vue解决遮罩层滚动方法
vue 遮罩层阻止默认滚动事件 在写移动端页面的时候,弹出遮罩层后,我们仍然可以滚动页面. vue中提供 @touchmove.prevent 方法可以完美解决这个问题 <div class=& ...
- vue实例的属性和方法
vue实例的属性和方法 1. 属性 vm.$el #指定要绑定的元素 vm.$data #Vue 实例的数据对象 vm.$options #获取自定义属性的值 new Vue({ customOpti ...
- Vue把父组件的方法传递给子组件调用(评论列表例子)
Vue把父组件的方法传递给子组件调用(评论列表例子) 效果展示: 相关Html: <!DOCTYPE html> <html lang="en"> < ...
- html select options & vue h render
html select options & vue h render https://developer.mozilla.org/en-US/docs/Web/HTML/Element/opt ...
随机推荐
- awk打印第n个参数到最后一个技巧/将n行组成一列
打印第n参数到最后一个参数 文本的NF不等,即字段长度不固定,想截取从$3到$NF 第一反应是使用循环 [root@localhost ~]# echo "1 2 3 4 5" | ...
- Struts2实现文件下载
实现文件下载: 1.导包:commons-fileload-xx.jar commons-io-xx.jar 2.jsp页面: <s:iterator value="#session. ...
- 百度网盘不限速下载软件 Pan Download
百度网盘不限速下载软件 Pan Download Pan Download下载软件是一款电脑端的快速下载器软件,您可以通过Pan Download直接下载百度网盘中的资源,此款软件下载速度快,下载压缩 ...
- ajax请求获取实时数据
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- javascript中this指向问题
本文参考http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html this是JavaScript的一个关 ...
- 我的前端故事----关于前端数据&逻辑的思考
最近重构了一个项目,一个基于redux模型的react-native项目,目标是在混乱的代码中梳理出一个清晰的结构来,为了实现这个目标,首先需要对项目的结构做分层处理,将各个逻辑分离出来,这里我是基于 ...
- 三栏布局,div左右盒子是定宽,中间是自适应
用弹性布局flex: 给父盒子加个display:flex; 给中间盒子设flex=1; /* 弹性盒子布局*/ .wrap{ width: 100%; height: 90px; display: ...
- BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]
4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...
- POJ 1755 Triathlon [半平面交 线性规划]
Triathlon Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6912 Accepted: 1790 Descrip ...
- EFCore数据库迁移命令整理
前言 因为现在用.net core 开发新项目,过程中需要经常涉及到数据命令的迁移,今天分别整EFCore 的两种迁移数据库的方式 1 程序包管理器控制台 , Package Manager Con ...