开开森森学前端之render函数

前言

使用vue这么久了,但是对render函数还是不怎么熟悉,所以写篇文章加深理解和记忆!方便日后熟练使用。

正文

mian.js中的new Vue中会传入render: h => h(App)

那么这个h其实可以用来创建元素。

他的第一个参数是必选参数

第二个和第三个都是可选参数

第一个参数就是当前要渲染的组件或者标签,也可以是个函数

第二个参数一个配置对象,里面可以传递一些html自带的原生属性

第三个参数可以是字符串或者数组 示例代码:

new Vue({
   render: h => {
      return h('div',{
        attrs:{
           id:'box'
        },
        style:{
           color:'red'
        }
      },'Dreams')
   }
}).$mount('#app')
复制代码

这里我们用render函数生成了一个idbox,颜色为红色,文本为Dreamsdiv元素。

问题又来了,假设我们渲染一个组件,组件里面要进行传值,那么该怎么书写?

new Vue({
   render: h => {
      return h(CountTo,{
        props:{
          endVal:100
        }
      })
   }
}).$mount('#app')
复制代码

那么这里我们就可以在render函数里使用props对组件进行传值操作了。

上面这个是一个数字过渡组件,我们传递endVal是为了告诉他到多少时停止

在此基础上,我们如果想给组件绑定事件呢?

new Vue({
   render: h => {
      return h(CountTo,{
        props:{
          endVal:100
        },
        on:{
          'on-animation-end':(val) => {
              console.log(val)
          }
        }
      })
   }
}).$mount('#app')
复制代码

实际上这里监听了一个事件,on-animation-end这个事件其实是CountTo组件通过$emit派发出来的. 然后我们又想给这个组件最外层绑定一个点击事件该怎么做?

new Vue({
   render: h => {
      return h(CountTo,{
        props:{
          endVal:100
        },
        on:{
          'on-animation-end':(val) => {
              console.log(val)
          }
        },
        nativeOn:{
            'click':() => {
                console.log('click')
            }
        }
      })
   }
}).$mount('#app')
复制代码

然后我们又想给这个组件定义一个class类名怎么办?

new Vue({
   render: h => {
      return h(CountTo,{
        'class':['count-to',true ? 'aa' : 'bb'],
        props:{
          endVal:100
        },
        on:{
          'on-animation-end':(val) => {
              console.log(val)
          }
        },
        nativeOn:{
            'click':() => {
                console.log('click')
            }
        }
      })
   }
}).$mount('#app')
复制代码

那么我们还想使用指令和插槽并且获取dom怎么办?

new Vue({
   render: h => {
      return h(CountTo,{
        'class':['count-to',true ? 'aa' : 'bb'],
        props:{
          endVal:100
        },
        domProps:{
          //dom上的一些属性,
          //因为现在是组件所以这样写会报错
          innerHTML:'123'
        },
        on:{
          'on-animation-end':(val) => {
              console.log(val)
          }
        },
        nativeOn:{
            'click':() => {
                console.log('click')
            }
        },
        directives:[],
        slot:'default',
        key:'',
        ref:'',
        scopedSlots:{},
      })
   }
}).$mount('#app')
复制代码

那假设现在需要给一个标签添加元素怎么添加?

我们把上面的干掉!

new Vue({
   render: h => h('div','123')
}).$mount('#app')
复制代码

这里的123是第三个参数,第二个参数我们不写直接留空

所以页面上会渲染出

<div>123</div>
复制代码

如果我们要在div元素里添加多个子元素呢? 那么肯定是个数组。

new Vue({
   render: h => h('div',{},[
     h('span','111'),
     h('span','222'),
   ])
}).$mount('#app')
复制代码

那么现在div里就有两个span标签了

<div>
    <span>111</span>
    <span>222</span>
</div>
复制代码

那么我们生成的东西如果很多且不固定呢?

那么这里如何使用循环呢?

那么这里我们新建一个组件文件

里面的内容是这样的

new Vue({
   render: h => h('div',{},[
     h('ul',{
        on:{
            'click':(event) => {
                console.log(event)
            }
        }
     },[
        h('li',{
            on:{
                'click':event => {
                    console.log(event)
                }
            }
        })
     ])
   ])
}).$mount('#app')
复制代码

那么现在div里就有一个ul标签包含一个li标签了

<div>
    <ul>
        <li></li>
    </ul>
</div>
复制代码

render里我们其实是没办法使用v-for指令的,所以我们要自己实现这个方法

let list = [{name:'Dreams'},{name:'Dreams2'}]
const getLiEleArr = h => {
    return list.map(item => h('li',{
        on:{
            'click':(event) => {
                console.log(event)
            }
        }
    },item.name))//标签内的内容
}
复制代码

这个方法写好了之后我们把刚刚上面的改造一下

new Vue({
   render: h => h('div',{},[
     h('ul',{
        on:{
            'click':(event) => {
                console.log(event)
            }
        }
     },getLiEleArr(h))
   ])
}).$mount('#app')
复制代码

那么这样页面上就成功的渲染出如下的标签:

<div>
    <ul>
        <li>Dreams</li>
        <li>Dreams2</li>
    </ul>
</div>
复制代码

同时li和ul也有点击事件

这里需要阻止事件冒泡,但render函数里也无法使用vue.stop修饰符 所以我们需要给刚刚的click里使用event.stopProgation()来阻止

但又有问题来了,我们知道使用v-for需要给每个元素加上key,但这里我们没有该怎么办?

回到刚刚的代码

let list = [{name:'Dreams'},{name:'Dreams2'}]
const getLiEleArr = h => {
    return list.map((item,index) => h('li',{
        on:{
            'click':(event) => {
                console.log(event)
            }
        },
        key:`item_${index}`//这里我们加上key
    },item.name))//标签内的内容
}
复制代码

那么到这里,相信大家也对render有了一个大概的了解了。

也就是说我们平时在模板里写的东西其实最后都会被编译为类似上面的语法!

总结

学好render函数在某些情况下可以让我们更好用js去控制一些细节的实现,但我们也会发现,render略显复杂,但是越复杂的东西才越有它存在的意义!

各位大佬,如果发现文中的错误,请指正,我会及时修改!

感谢大佬们能在百忙中能阅读完这篇文章!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值