前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue 中 render 函数有点意思

Vue 中 render 函数有点意思

作者头像
前端小智@大迁世界
发布2020-05-12 14:30:03
9880
发布2020-05-12 14:30:03
举报
文章被收录于专栏:终身学习者终身学习者

作者:Joshua Bemenderfer 译者:前端小智 来源:vuejsbook.com

我们知道 Vue 模板是非常强大的,基本可以完成我们日常开发的所有任务。但是,有一些用例,如基于输入或插槽值创建动态组件方式,render 函数会比模板完成的更好也更出色。

用过 React 开发的人对 render 函数应该非常熟悉,因为React组件通过 JSX和 render 函数来构建的。 尽管Vue render 函数也可以用JSX编写,但在这里我们使用原生 JS方式,因为这样,我们可以更轻松地了解Vue组件系统的一些基础。

值得注意的是,Vue 的模板实际上在编译时也是会先解析成 render 函数表示方式。 模板只是在render 函数之上提供了一个方便且熟悉的语法糖。 尽管 render 函数更强大,但render函数可读性很差,相对用的也比较少了。

创建组件

带有 render 函数的组件没有template标记或属性。 相反,该组件定义了一个了名为render的函数,该函数接收一个reateElement(renderElement: String | Component, definition: Object, children: String | Array)参数(由于某种原因,通常别名为h,归咎于JSX)并返回使用该函数创建的元素,其他一切保持不变,来看看事例:

代码语言:javascript
复制
export default {
  data() {
    return {
      isRed: true
    }
  },

  /*
   * <template>
   *   <div :class="{'is-red': isRed}">
   *     <p>这是一个 render 事例</p>
   *   </div>
   * </template>
   */
  // render 中的渲染结果与上面等价
  render(h) {
    return h('div', {
      'class': {
        'is-red': this.isRed
      }
    }, [
      h('p', '这是一个 render 事例')
    ])
  }
}

render 函数中如何表示指令

Vue 模板具有各种便捷功能,以便向模板添加基本逻辑和绑定功能,如 v-ifv-forv-moel指令等。 在render函数中是无法使用这些指令的。 取而代之的是以纯 JS 来实现,对于大多数指令而言,这也是比较简单的。

v-if

v-if 用纯 JS 实现很简单,只需围绕createElement调用使用 if(expr)语句即可。

v-for

v-for可以使用for-ofArray.mapArray.filter等的JS方法中的任何一种来实现。我们可以通过非常有趣的方式将它们组合在一起,以实现过滤或状态切片,而无需计算属性。

例如,有以下 Vue 的模板代码

代码语言:javascript
复制
<template>
  <ul>
    <li v-for="pea of pod">
      
    </li>
  </ul>
</template>

可以用下面的 render 函数来实现上面的效果:

代码语言:javascript
复制
render(h) {
  return h('ul', this.pod.map(pea => h('li', pea.name)));
}
v-model

我们知道,v-model只是bind属性与value的语法糖,并在触发input事件时设置数据属性。但是,在render函数没有这样的简写,我们需要自己实现。

假设,在 Vue 中,我们有如下的结构:

代码语言:javascript
复制
<template>
  <input v-model='myBoundProperty'/>
</template>

上面代码等价于:

代码语言:javascript
复制
<template>
  <input :value="myBoundProperty" @input="myBoundProperty = $event.target.value"/>
</template>

在 render 函数中可以用下面方式来实现上面的代码:

代码语言:javascript
复制
render(h) {
  return h('input', {
    domProps: {
      value: this.myBoundProperty
    },
    on: {
      input: e => {
        this.myBoundProperty = e.target.value
      }
    }
  })
}

v-bind

attributeproperty 这两种类型的绑定被放在元素定义中,如arttrspropsdomProps( valueinnerHTML之类的东西)。

代码语言:javascript
复制
render(h) {
  return h('div', {
    attrs: {
      // <div :id="myCustomId">
      id: this.myCustomId
    },

    props: {
      // <div :someProp="someonePutSomethingHere">
      someProp: this.someonePutSomethingHere
    },

    domProps: {
       // <div :value="somethingElse">
      value: this.somethingElse
    }
  });
}

需要注意的是,对于 classstyle的绑定是直接在定义的根进行处理,而不是作为attrspropsdomProps处理。

代码语言:javascript
复制
render(h) {
  return h('div', {
    // “类”是JS中的保留关键字,因此必须引用它。
    'class': {
      myClass: true,
      theirClass: false
    },

    style: {
      backgroundColor: 'green'
    }
  });
}

v-on

对事件处理程也是直接添加到元素定义中 on 定义

代码语言:javascript
复制
render(h) {
  return h('div', {
    on: {
      click(e) {
        console.log('I got clickeded!')
      }
    }
  });
}

事件的修饰符可以在处理程序内部实现:

  • .stop -> e.stopPropagation()
  • .prevent -> e.preventDefault()
  • .self -> if (e.target !== e.currentTarget) return

键盘修饰符

  • .[TARGET_KEY_CODE] -> if (event.keyCode !== TARGET_KEY_CODE) return
  • .[MODIFIER] -> if (!event.MODIFIERKey) return
特殊属性

Slots 可以通过this.$slots作为createElement()节点的数组来访问插槽。

作用域插槽存储在this.$scopedSlots[scope](props:object) 中,作为返回createElement()节点数组的函数。


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://vuejsbook.com/introdu...

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建组件
  • render 函数中如何表示指令
    • v-if
      • v-for
        • v-model
        • v-bind
        • v-on
          • 特殊属性
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档