vue中的render函数h()函数函数式组件

Posted 奥特曼 

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue中的render函数h()函数函数式组件相关的知识,希望对你有一定的参考价值。

一、什么是render

官网:用于编程式地创建组件虚拟 DOM 树的函数。

在我们使用webpack脚手架创建项目时,都能在main.js中看到一个render函数

import Vue from 'vue'
import App from './App.vue'

new Vue(
  render: h => h(App)
).$mount('#app')

对于render函数 es6中写成了箭头函数 

es5写法:

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

实际上createElement只是形参用h代表了,h() 是 hyperscript 的简称——意思是“能生成 html (超文本标记语言) 的 javascript”。这个名字来源于许多虚拟 DOM 实现默认形成的约定。一个更准确的名称应该是 createVnode(),但当你需要多次使用渲染函数时,一个简短的名字会更省力。

二、vue中的render

字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode

如果组件是一个函数组件,渲染函数还会接收一个额外的 context 参数,为没有实例的函数组件提供上下文信息。

Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

h()函数用法还是比较多的

// 除了类型必填以外,其他的参数都是可选的
h('div')
h('div',  id: 'foo' )

// attribute 和 property 都能在 prop 中书写
// Vue 会自动将它们分配到正确的位置
h('div',  class: 'bar', innerHTML: 'hello' )

// props modifiers such as .prop and .attr can be added
// with '.' and `^' prefixes respectively
h('div',  '.name': 'some-name', '^width': '100' )

// 类与样式可以像在模板中一样
// 用数组或对象的形式书写
h('div',  class: [foo,  bar ], style:  color: 'red'  )

// 事件监听器应以 onXxx 的形式书写
h('div',  onClick: () =>  )

// children 可以是一个字符串
h('div',  id: 'foo' , 'hello')

// 没有 props 时可以省略不写
h('div', 'hello')
h('div', [h('span', 'hello')])

// children 数组可以同时包含 vnodes 与字符串
h('div', ['hello', h('span', 'hello')])

得到的 vnode 为如下形式:

const vnode = h('div',  id: 'foo' , [])

vnode.type // 'div'
vnode.props //  id: 'foo' 
vnode.children // []
vnode.key // null

当然我们常见的template的形式(Vue 的模板)实际上被编译成了渲染函数。

export default  
    render (h) 
        const p = h('p', 'hi')
        return h('div',  class: 'red' , [p, p])
      

 

三、函数式组件

函数式组件是一种定义自身没有任何状态的组件的方式。它们很像纯函数:接收 props,返回 vnodes。函数式组件在渲染过程中不会创建组件实例 (也就是说,没有 this),也不会触发常规的组件生命周期钩子。

官网函数式组件格式:

当一个组件没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法。实际上,它只是一个接受一些 prop 的函数。在这样的场景下,我们可以将组件标记为 functional,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。一个函数式组件就像这样:

export default Vue.component('render-component',  // 该组件抽成js文件,
  functional: true,
  // 提供第二个参数作为上下文
  render: function (createElement, context) 
    return createElement('h1', '我是函数式子组件')
  
)

组件需要的一切都是通过 context 参数传递,它是一个包括如下字段的对象:

  • props:提供所有 prop 的对象
  • children:VNode 子节点的数组
  • slots:一个函数,返回了包含所有插槽的对象
  • scopedSlots:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
  • data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
  • parent:对父组件的引用
  • listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
  • injections:(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的 property。

函数式组件可以像普通组件一样被注册和使用。如果你将一个函数作为第一个参数传入 h,它将会被当作一个函数式组件来对待。
 

补充 h函数使用场景

button.vue

<script>
export default 
  props: 
    type: 
      type: String,
      default: 'normal'
    ,
    text: 
      type: String,
      default: 'normal'
    ,
    size: 
      type: String,
      default: 'medium'
    
  ,
  computed: 
    tag () 
      switch (this.type) 
        case 'success':
          return 1
        case 'danger':
          return 2
        case 'warning':
          return 3
        default:
          return 1
      
    
  ,
  render (h) 
    return h('div', 
      class: 
        btn: true,
        buttom: 'name',
        'btn-success': this.type === 'success',
        'btn-danger': this.type === 'danger',
        'btn-warning': this.type === 'warning',
        'btn-mini': this.size === 'mini',
        'btn-small': this.size === 'small',
        'btn-medium': this.size === 'medium'
      ,
      domProps: 
        innerText: this.text
      ,
      on: 
        click: this.handleClick
      
    )
  ,
  methods: 
    handleClick () 
      console.log('button')
    
  

</script>

<style lang="less" scoped>
.buttom 
  padding: 10px 0;
  margin: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;


.buttom:hover 
  background: #c9c9c9;


.btn-success 
  background: #48ff8b;
  color: #fff;


.btn-danger 
  background: #ff4848;
  color: #fff;


.btn-warning 
  background: #ffbf48;
  color: #fff;


.btn-small 
  width: 120px;
  height: 20px;


.btn-medium 
  width: 120px;
  height: 30px;


.btn-mini 
  width: 120px;
  height: 10px;

</style>

使用

    <Button type="danger" text="名字" size="mini"></Button>
    <Button type="warning" text="名字" size="small"></Button>
    <Button type="success" text="名字" size="mini"></Button>
    <Button type="danger" text="名字" size="medium"></Button>
    <Button type="success" text="名字" size="mini"></Button>
    <Button type="warning" text="名字" size="medium"></Button>

以上是关于vue中的render函数h()函数函数式组件的主要内容,如果未能解决你的问题,请参考以下文章

在vue中使用render函数

vue 函数组件的应用及场景

vue中的render函数(通俗易懂)

Vue 开发实战基础篇 # 10:生命周期的应用场景和函数式组件

使用render函数渲染组件

vue-12-渲染函数 & JSX