Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue 中 render 函数有点意思 #196

Open
husky-dot opened this issue Feb 27, 2020 · 0 comments
Open

Vue 中 render 函数有点意思 #196

husky-dot opened this issue Feb 27, 2020 · 0 comments

Comments

@husky-dot
Copy link
Owner

作者:Joshua Bemenderfe

译者:前端小智

来源:vuejsbook.com

点赞再看,养成习惯

本文 GitHub https://github.com/qq449245884/xiaozhi 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。

我们知道 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)并返回使用该函数创建的元素,其他一切保持不变,来看看事例:

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 的模板代码

<template>
  <ul>
    <li v-for="pea of pod">
      
    </li>
  </ul>
</template>

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

render(h) {
  return h('ul', this.pod.map(pea => h('li', pea.name)));
}

v-model

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

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

<template>
  <input v-model='myBoundProperty'/>
</template>

上面代码等价于:

<template>
  <input :value="myBoundProperty" @input="myBoundProperty = $event.target.value"/>
</template>

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

render(h) {
  return h('input', {
    domProps: {
      value: this.myBoundProperty
    },
    on: {
      input: e => {
        this.myBoundProperty = e.target.value
      }
    }
  })
}

v-bind

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

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处理。

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

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

v-on

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

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/introduction-to-vue-render-functions-with-examples


交流

文章每周持续更新,可以微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,另外关注公众号,后台回复福利,即可看到福利,你懂的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant