1. 动态组件
-
动态组件就是 component组件 , 组件身上可以绑定一个is属性, 用来表示某一个组件。
-
通过使用保留的 元素,动态地绑定到它的 is 特性,我们让多个组件可以使用同一个挂载点,并动态切换。根据 v-bind:is=“组件名” 中的组件名去自动匹配组件,如果匹配不到则不显示。
2. is属性(改变挂载的组件,只需要修改is指令的值即可。)
- 我们html中有一些标签是规定它的直接子元素的 , 比如 ul li ol li selector option table这类型标签
- 不能直接用常规的组件使用方式, 必须在对应直接子元素上绑定 is属性
<div id="app">
<table>
<tr>
<td>aa</td>
<td>bb</td>
<td>cc</td>
</tr>
<!-- is = 组件名称 -->
<tr is = 'my-table'></tr>
</table>
</div>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 动态组件</title>
<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<button @click='toShow'>点击显示子组件</button>
<component v-bind:is="which_to_show"></component>
</div>
<script>
// 创建根实例
new Vue({
el: '#app',
data:{
which_to_show:'first'
},
methods:{
toShow:function(){
var arr = ["first","second","third"];
var index = arr.indexOf(this.which_to_show);
if(index<2){
this.which_to_show = arr[index+1];
}else{
this.which_to_show = arr[0];
}
}
},
components:{
first:{
template:'<div>这是子组件1<div>'
},
second:{
template:'<div>这是子组件2<div>'
},
third:{
template:'<div>这是子组件3<div>'
},
}
})
</script>
</body>
</html>
3. keep-alive组件
-
将组件的内容存在浏览器缓存中, 当我们需要重复渲染的时候, 就从浏览器缓存中去调用,这样可以减少性能消耗
-
动态切换掉的组件(非当前显示的组件)是被移除掉了,如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 动态组件</title>
<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<button @click='toShow'>点击显示子组件</button>
<!----或者<component v-bind:is="which_to_show" keep-alive></component>也行----->
<keep-alive>
<component v-bind:is="which_to_show" ></component>
</keep-alive>
</div>
<script>
// 创建根实例
new Vue({
el: '#app',
data:{
which_to_show:'first'
},
methods:{
toShow:function(){
var arr = ["first","second","third"];
var index = arr.indexOf(this.which_to_show);
if(index<2){
this.which_to_show = arr[index+1];
}else{
this.which_to_show = arr[0];
} console.log(this.$children);
}
},
components:{
first:{
template:'<div>这是子组件1<div>'
},
second:{
template:'<div>这是子组件2<div>'
},
third:{
template:'<div>这是子组件3<div>'
},
}
})
</script>
</body>
</html>
<keep-alive>
<component is = "A"></component>
</keep-alive>
说明:
- 初始情况下,vm.$children属性中只有一个元素(first组件),
- 点击按钮切换后,vm.$children属性中有两个元素,
- 再次切换后,则有三个元素(三个子组件都保留在内存中)。
- 之后无论如何切换,将一直保持有三个元素。
4. 不常用指令
- v-text vs v-html
- 都是用来将数据插入DOM中, 但是v-html可以解析标签类型数据
- v-cloak 解决 {{}} 语法短暂原样输出
- v-pre 原样输出
- v-once 只渲染一次
- 代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<style>
[v-cloak]{
display: none;
/* visibility: hidden; */
/* opacity: 0; */
}
</style>
</head>
<body>
<div id="app">
<h3> v-text </h3>
<p> {{ msg }} </p>
<p v-text = "msg"></p>
<div v-text = "title"></div>
<h3> v-html </h3>
<div v-html = "title"></div>
<div v-html = "msg"></div>
<h3> v-pre </h3>
<p v-pre>
{{ msg }}
</p>
<h3> v-cloak </h3>
<p v-cloak>
{{ msg }}
</p>
<h3> v-once </h3>
<p v-once>
{{ msg }}
</p>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
msg: 'hello vue.js',
title: '<h3> hello title </h3>'
}
})
</script>
</html>
5. 异步组件
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。例如:
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
如你所见,这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。这里的 setTimeout 是为了演示用的,如何获取组件取决于你自己。一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用:
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包,这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
- 异步组件也是一个函数, 只不过这个函数使用Promise,函数有一个返回值
代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../../basic-source/vue.js"></script>
</head>
<body>
<div id="app">
<async-com></async-com>
</div>
</body>
<script>
var result = new Promise(function( resolve, reject ){
resolve({
template: '<div> 异步组件 </div>'
})
})
Vue.component('AsyncCom',async () => {
const tpl = await result.then( res => res)
return tpl
})
// Vue.component('async-com', function (resolve, reject) {
// setTimeout(function () {
// // 向 `resolve` 回调传递组件定义
// resolve({
// template: '<div>I am async!</div>'
// })
// }, 1000)
// })
new Vue({
el: '#app'
})
</script>
</html>
接下来,我们可以封装一个异步组件,
代码如下:
/*
js文件
*/
const asyncCom = {
createAsyncCom({
selector,
asyncComName,
methods,
data,
watch,
computed,
filters,
directives,
components,
delay}){
var result = new Promise(function( resolve, reject ){
resolve({
template: selector,
methods,
data,
watch,
computed,
filters,
directives,
components
})
})
setTimeout(()=>{
Vue.component(asyncComName,async () => {
const tpl = await result.then( res => res)
return tpl
})
},delay)
}
}
export default {
createAsyncCom: asyncCom.createAsyncCom
}
. 高阶组件(HOC) higt order component
高阶组件(HOC)是 React 生态系统的常用词汇,React 中代码复用的主要方式就是使用高阶组件,并且这也是官方推荐的做法。而 Vue 中复用代码的主要方式是使用 mixins,并且在 Vue 中很少提到高阶组件的概念,这是因为在 Vue 中实现高阶组件并不像 React 中那样简单,原因在于 React 和 Vue 的设计思想不同,但并不是说在 Vue 中就不能使用高阶组件,只不过在 Vue 中使用高阶组件所带来的收益相对于 mixins 并没有质的变化。本篇文章主要从技术性的角度阐述 Vue 高阶组件的实现,且会从 React 与 Vue 两者的角度进行分析。
高阶组件是一个函数, 这个函数的作用是进行组件的复用
所谓高阶组件其实就是高阶函数啦,React 和 Vue 都证明了一件事儿:一个函数就是一个组件。所以组件是函数这个命题成立了,那高阶组件很自然的就是高阶函数,即一个返回函数的函数,我们知道在 React 中写高阶组件就是在写高阶函数,很简单,那是不是在 Vue 中实现高阶组件也同样简单呢?其实 Vue 稍微复杂,甚至需要你对 Vue 足够了解,接下来就让我们一块在 Vue 中实现高阶组件,在文章的后面会分析为什么同样都是 函数就是组件 的思想,Vue 却不能像 React 那样轻松的实现高阶组件。
了解了这些,接下来我们就可以开始着手实现 Vue 高阶组件了,为了让大家有一个直观的感受,我仍然会使用 React 与 Vue 进行对比的讲解。首先是一个基本的 Vue 组件,我们常称其为被包装组件(WrappedComponent),假设我们的组件叫做 BaseComponent:
base-component.vue
<template>
<div>
<span @click="handleClick">props: {{test}}</span>
</div>
</template>
<script>
export default {
name: 'BaseComponent',
props: {
test: Number
},
methods: {
handleClick () {
this.$emit('customize-click')
}
}
}
</script>
我们观察一个 Vue 组件主要观察三点:props、event 以及 slots。对于 BaseComponent 组件而言,它接收一个数字类型的 props 即 test,并发射一个自定义事件,事件的名称是:customize-click,没有 slots。我们会这样使用该组件:
<base-component @customize-click="handleCustClick" :test="100" />
代码示例
class HOC {
//复用性代码
sum(){
//一万行代码
return 1+1
}
init(Com){
return <Com sum = { this.sum }/>
}
}
export default {
init: HOC.init
}
const A = init(A)
const B = init(B)