Vue render函数 异步组件 动态组件 递归组件和函数式组件
1.render函数1.场景:有些代码在 template 里面写会重复很多,所以这个时候 render 函数就有作用啦// 根据 props 生成标签// 初级<template><div><div v-if="level === 1"> <slot></slot> </div><p v-else-if="level
·
1.render函数
1.场景:有些代码在 template 里面写会重复很多,所以这个时候 render 函数就有作用啦
// 根据 props 生成标签
// 初级
<template>
<div>
<div v-if="level === 1"> <slot></slot> </div>
<p v-else-if="level === 2"> <slot></slot> </p>
<h1 v-else-if="level === 3"> <slot></slot> </h1>
<h2 v-else-if="level === 4"> <slot></slot> </h2>
<strong v-else-if="level === 5"> <slot></slot> </stong>
<textarea v-else-if="level === 6"> <slot></slot> </textarea>
</div>
</template>
// 优化版,利用 render 函数减小了代码重复率
<template>
<div>
<child :level="level">Hello world!</child>
</div>
</template>
<script type='text/javascript'>
import Vue from 'vue'
Vue.component('child', {
render(h) {
const tag = ['div', 'p', 'strong', 'h1', 'h2', 'textarea'][this.level-1]
return h(tag, this.$slots.default)
},
props: {
level: { type: Number, required: true }
}
})
export default {
name: 'hehe',
data() { return { level: 3 } }
}
</script>
2.render 和 template 的对比
前者适合复杂逻辑,后者适合逻辑简单;
后者属于声明是渲染,前者属于自定Render函数;
前者的性能较高,后者性能较低。
2.异步组件
场景:项目过大就会导致加载缓慢,所以异步组件实现按需加载就是必须要做的事啦
1.异步注册组件
3种方法
// 工厂函数执行 resolve 回调
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包, 这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
// 工厂函数返回 Promise
Vue.component(
'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
// 工厂函数返回一个配置化组件对象
const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
异步组件的渲染本质上其实就是执行2次或者2次以上的渲染, 先把当前组件渲染为注释节点, 当组件加载成功后, 通过 forceRender 执行重新渲染。或者是渲染为注释节点, 然后再渲染为loading节点, 在渲染为请求完成的组件
2.路由的按需加载
webpack< 2.4 时
{
path:'/',
name:'home',
components:resolve=>require(['@/components/home'],resolve)
}
webpack> 2.4 时
{
path:'/',
name:'home',
components:()=>import('@/components/home')
}
import()方法由es6提出,import()方法是动态加载,返回一个Promise对象,then方法的参数是加载到的模块。类似于Node.js的require方法,主要import()方法是异步加载的。
3.动态组件
场景:做一个 tab 切换时就会涉及到组件动态加载
<component v-bind:is="currentTabComponent"></component>
但是这样每次组件都会重新加载,会消耗大量性能,所以<keep-alive> 就起到了作用
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
这样切换效果没有动画效果,这个也不用着急,可以利用内置的<transition>
<transition>
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
</transition>
4.递归组件
场景:如果开发一个 tree 组件,里面层级是根据后台数据决定的,这个时候就需要用到动态组件
// 递归组件: 组件在它的模板内可以递归的调用自己,只要给组件设置name组件就可以了。
// 设置那么House在组件模板内就可以递归使用了,不过需要注意的是,
// 必须给一个条件来限制数量,否则会抛出错误: max stack size exceeded
// 组件递归用来开发一些具体有未知层级关系的独立组件。比如:
// 联级选择器和树形控件
<template>
<div v-for="(item,index) in treeArr">
子组件,当前层级值: {{index}} <br/>
<!-- 递归调用自身, 后台判断是否不存在改值 -->
<tree :item="item.arr" v-if="item.flag"></tree>
</div>
</template>
<script>
export default {
// 必须定义name,组件内部才能递归调用
name: 'tree',
data(){
return {}
},
// 接收外部传入的值
props: {
item: {
type:Array,
default: ()=>[]
}
}
}
</script>
递归组件必须设置name 和结束的阀值
5.函数式组件
定义:无状态,无法实例化,内部没有任何生命周期处理方法
组件需要的一切都是通过 context 参数传递
context 属性有:
1.props:提供所有 prop 的对象
2.children: VNode 子节点的数组
3.slots: 一个函数,返回了包含所有插槽的对象
4.scopedSlots: (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
5.data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
6.parent:对父组件的引用
7.listeners: (2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
8.injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性
<template functional>
<div v-for="(item,index) in props.arr">{{item}}</div>
</template>
6.components和 Vue.component
components:局部注册组件
export default{
components:{home}
}
Vue.component:全局注册组件
Vue.component('home',home)
更多推荐
已为社区贡献1条内容
所有评论(0)