在上一篇文章开篇中,已经出现了render函数但是在中级篇中我们并没有使用,那么就在高级篇里面让我们来看一下如何利用render函数来做最后的优化吧:
- 高级篇,使用render函数自己进行拼接创建。
createElement render render选项与h函数
-
指定组件显示的内容:
new Vue({选项})- el 选项,通过一个选择器找到容器,容器内容就是组件内容
- template 选项,
<div>组件内容</div>作为组件内容 - render选项,它是一个函数,函数回默认传人createElement的函数(h),这个函数用来创建结构,再render函数返回渲染为组件内容。它的优先级更高。
//import App from './App.vue'
//new Vue({
// render:h=>h(App)
//}).mount('#app')
// h() =====> createElement()
// h(App) =====> 根据APP组件创建html结构
// render的返回值就是html结构,渲染到#app容器
// h() 函数参数,1.节点名称 2. 属性|数据 是对象 3. 子节点
1)shop-bread-item.vue
<template>
<div class="shop-bread-item">
<RouterLink v-if="to" :to="to"><slot /></RouterLink>
<span v-else><slot /></span>
- <i class="iconfont icon-angle-right"></i>
</div>
</template>
2)shop-bread.vue
<script>
import { h } from 'vue'
export default {
name: 'ShopBread',
render () {
// 用法
// 1. template 标签去除,单文件组件
// 2. 返回值就是组件内容
// 3. vue2.0 的h函数传参进来的,vue3.0 的h函数导入进来
// 4. h 第一个参数 标签名字 第二个参数 标签属性对象 第三个参数 子节点
// 需求
// 1. 创建shop-bread父容器
// 2. 获取默认插槽内容
// 3. 去除xtx-shop-item组件的i标签,因该由render函数来组织
// 4. 遍历插槽中的item,得到一个动态创建的节点,最后一个item不加i标签
// 5. 把动态创建的节点渲染再xtx-bread标签中
const items = this.$slots.default()
const dymanicItems = []
items.forEach((item, i) => {
dymanicItems.push(item)
if (i < (items.length - 1)) {
dymanicItems.push(h('i', { class: 'iconfont icon-angle-right' }))
}
})
return h('div', { class: 'shop-bread' }, dymanicItems)
}
}
</script>
<style lang='less'>
// 去除 scoped 属性,目的:然样式作用到shop-bread-item组件
.shop-bread{
display: flex;
padding: 25px 10px;
&-item {
a {
color: #666;
transition: all .4s;
&:hover {
color: @xtxColor;
}
}
}
i {
font-size: 12px;
margin-left: 5px;
margin-right: 5px;
line-height: 22px;
// 样式的方式,不合理
// &:last-child {
// display: none;
// }
}
}
</style>
使用代码
<!-- 面包屑 -->
<ShopBread>
<ShopBreadItem to="/">首页</ShopBreadItem>
<ShopBreadItem to="/category/1005000">电器</ShopBreadItem>
<ShopBreadItem >空调</ShopBreadItem>
</ShopBread>
-
总结,一下知识点
-
render 是vue提供的一个渲染函数,优先级大于el,template等选项,用来提供组件结构。
-
注意:
- vue2.0 render函数提供render(h){}函数用来创建节点
- vue3.0 函数由 vue 直接提供,需要按需导入
import { h } from 'vue'
-
this.$slots.default() 获取默认插槽的节点结构,按照要求拼接结构。
-
h函数的传参 tag 标签名|组件名称, props 标签属性|组件属性, node 子节点|多个节点
-
具体参考 render
-
-
注意:不要在 shop-bread 组件插槽写注释,也会被解析,改善用户体验
基于jsx方式实现
<script>
// import { h } from 'vue'
export default {
name: 'ShopBread',
render () {
// vue2的render函数的形参是 h 函数
// vue3中h函数是导入的
// createElement(标签名称, 标签的属性, 标签的子元素)
// console.dir(this.$slots.default())
// 获取ShopBread组件的所有的插槽里面填充组件实例
const items = this.$slots.default()
const results = []
items.forEach((item, index) => {
results.push(item)
// 手动生成一个i图标,添加到面包屑项目的后面
// const iTag = h('i', { class: 'iconfont icon-angle-right' })
if (index < items.length - 1) {
// results.push(iTag)
results.push(<i className='iconfont icon-angle-right'></i>)
}
})
// div的子节点应该动态生成:更加插槽的内容动态生成
// return h('div', { class: 'shop-bread' }, results)
return <div className='shop-bread'>{results}</div>
}
}
</script>
关于jsx:
- jsx其实就是直接在js代码中写HTML标签
- 标签中插入的动态值使用单个花括号(插值表达式)
- class名称需要换成className