Vue中的Render

12 篇文章 0 订阅
0 篇文章 0 订阅

前言

Vue中的render提供了一种以函数的方式写HTML的思路,比起template具有更强的可控性,也是一种更接近编译器的编写方式。在一些场景中,比如说开发组件库,包括数据模板渲染、组件按需加载、引入自定义组件插槽等等。这些时候我们往往需要用这种完全编程的方式来解决。本文提供render介绍和一些基本的实例。


一、虚拟DOM

谈到render函数就不得不先阐述清楚虚拟DOM:

人人都清楚DOM 是浏览器解析 HTML ,从而得来的一个树形逻辑对象。但如果用 Object 来代表一个节点,这个节点便叫做虚拟节点( Virtual Node 简写为 VNode ),由 VNode 树组成虚拟DOM。

使用虚拟DOM会有实际的好处

Web 页面的大多数操作和逻辑的本质就是不停地修改 DOM 元素,但是 DOM 操作太慢了,过于频繁的 DOM 操作可能会导致整个页面掉帧、卡顿甚至失去响应。操纵DOM元素的代价是昂贵的

仔细想一想,很多 DOM 操作是可以打包(多个操作压成一个)和合并(一个连续更新操作只保留最终结果)的,同时 JS 引擎的计算速度要快得多,所以为什么不把 DOM 操作先通过JS计算完成后统一来一次大招操作DOM呢,于是就有了虚拟DOM的概念。当然,虚拟DOM操作的核心是Diff算法,也就是比较变化前后Vnode的不同,计算出最小的DOM操作来改变DOM,提高性能。使用虚拟DOM往往是廉价的

二、CreateElement函数

创建虚拟DOM的手段是使用CreateElement函数

render: function (createElement) {
  return createElement(App);
}

在vue中,可以使用 h 代替 createElement,然后以上代码可以通过使用 ES6 箭头函数缩短:

render: h => h (App)

vue版本最多需要三个参数:

render: h => {
  return h('div', {}, [...])
}

第一种是元素的类型(以上显示为 div)。

第二个是数据对象。 我们在这里主要包括:props, attrs, dom props, class 和 style。

第三个是一组子节点。 然后,我们将嵌套调用并最终返回一个虚拟 DOM 节点树。

三、基础实例

以下是一个最基本的实例,包含了简单的渲染用法、标签、props、slot、点击事件:

<h1 class="wii-first">
    第一个组件<slot></slot>
    <slot name="subtitle"></slot>,此处是data的值: {{msg}}
    <button @click="clickHandler">
        点我改变内部data的值
    </button>
</h1>

以上的代码用render函数的方式编写如下:

export default {
  name: 'wii-first',
  data() {
    return {
      msg: 0
    }
  },
  props: {
    level: {
      type: [Number, String],
      required: true
    }
  },
  render: function(createElement) {
    this.$slots.subtitle = this.$slots.subtitle || []
    return createElement(
      'h' + this.level, // tag name 标签名称,上面的代码假设此处是1
      {
        class: 'wii-first'
      },
      // this.$slots.default, // 子组件中的slot 单个传递
      // this.$slots.subtitle,
      [
        '第一个组件, ',
        ...this.$slots.default, // 默认slots传递
        ...this.$slots.subtitle, // 具名slots传递
        ',此处是data的值: ',
        this.msg,
        createElement('button', {
          on: {
            click: this.clickHandler
          },
        }, '点我改变内部data值')
      ]
    )
  },
  methods: {
    clickHandler() {
      this.msg = Math.ceil(Math.random() * 1000)
    }
  }
}

接下来把上面用render写好的Demo,再引入到组件中,如下:
 

<template>
  <div id="app">
    <wii-first level="1">我是标题 <span slot="subtitle">我是subtitle</span></wii-first>
  </div>
</template>

<script>
import WiiFirst from './components/first/index.vue'
export default {
  name: 'app',
  components: {
    WiiFirst
  },
  data() {
    return {

    }
  }
}
</script>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值