内置组件的使用
引用vue官网中内置组件,点我去官网
component
Props:
is - string | ComponentDefinition | ComponentConstructor
inline-template - boolean
用法:
渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。
<!-- 动态组件由 vm 实例的属性值 `componentId` 控制 -->
<component :is="componentId"></component>
<!-- 也能够渲染注册过的组件或 prop 传入的组件 -->
<component :is="$options.components.child"></component>
其中component又叫动态组件,属性中 is 指定渲染的组件。
代码解释如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.css">
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 1、
<div id="app">
<com-a></com-a>
<com-b></com-b>
-----------------
<component is="comA"></component>
<component is="comB"></component>
</div> -->
<!--2、-->
<div id="app">
<ul class="nav nav-tabs">
<!-- 这里的item是是数组中的每一个对象 例如 { name: 'fqniu', container: '吃美食' } -->
<li class="nav-item" v-for="(item,idx) in tablist" v-on:click="changeTab(item)">
<!-- 这里的class判断是否comNum等于item.name, 如果相等 则样式为 active -->
<a class="nav-link" href="#" v-bind:class="{active:comNum===item.name}">{{ item.name }}--{{idx}}</a>
</li>
</ul>
<div class="container p-3">
<!-- 动态组件的使用-->
<component :is="comNum"></component>
</div>
</div>
<script>
// 1、第一种 直接使用 component
// const vm = new Vue({
// el: '#app',
// components: {
// comA: {
// name: 'comA',
// template: `<div>comA</div>`
// },
// comB: {
// name: 'comB',
// template: `<div>comB</div>`
// }
// }
// })
// 2、
// 点击tab栏切换内容 通过点击时 切换不同的组件 comNum
// 进而改变tab栏选项对应的内容
const vm = new Vue({
el: '#app',
data: {
tablist: [{
name: 'fqniu',
container: '吃美食'
}, {
name: 'niuniu',
container: '学游泳'
}, {
name: 'erniu',
container: '宅屋看书'
}, {
name: 'shaniu',
container: '敲代码'
}],
comNum: 'fqniu'
},
methods: {
changeTab(item) {
this.comNum = item.name
}
},
created() {
this.tablist.forEach(item => {
Vue.component(item.name, {
template: `<div>${item.container}</div>`
})
});
}
})
</script>
</body>
</html>
keep-alive
Props:
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。
用法:
< keep-alive > 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
和 < transition> 相似,< keep-alive > 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。
当组件在 < keep-alive> 内被切换,它的 activated 和 deactivated
这两个生命周期钩子函数
将会被对应执行。
在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 < keep-alive> 树内的所有嵌套组件中触发。
主要用于保留组件状态或避免重新渲染。
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一起使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
注意,< keep-alive > 是用在其一个直属的子组件被开关的情形。如果你在其中有 v-for 则不会工作。如果有上述的多个条件性的子元素,< keep-alive> 要求同时只有一个子元素被渲染。
2.1.0 新增 include and exclude
include 和 exclude 属性
允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。
2.5.0 新增 max
最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。
<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>
< keep-alive> 不会在函数式组件中正常工作,因为它们没有缓存实例。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.css">
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<ul class="nav nav-tabs">
<li class="nav-item" v-for="(item,idx) in tablist" v-on:click="changeTab(item)">
<a class="nav-link" href="#" v-bind:class="{active:comNum===item.name}">{{ item.name }}--{{idx}}</a>
</li>
</ul>
<div class="container p-3">
<keep-alive>
<!-- 缓存组件 保留组件状态 避免重新渲染 -->
<component :is="comNum"></component>
</keep-alive>
</div>
</div>
<script>
// 点击tab栏切换内容 上一个内容里面的数据还存在,并没有销毁
const vm = new Vue({
el: '#app',
data: {
tablist: [{
name: 'fqniu',
container: '吃美食'
}, {
name: 'niuniu',
container: '学游泳'
}, {
name: 'erniu',
container: '宅屋看书'
}, {
name: 'shaniu',
container: '敲代码'
}],
comNum: 'fqniu'
},
methods: {
changeTab(item) {
this.comNum = item.name
}
},
created() {
this.tablist.forEach(item => {
Vue.component(item.name, {
data() {
return {
num: 1
}
},
methods: {
change() {
this.num++
}
},
created() {
console.log('created', item)
},
distoryed() {
console.log('distory', item)
},
template: `<div>${item.container}
<button @click="change">这是点击增加的{{num}}</button>
</div>`
})
});
}
})
</script>
</body>
</html>
-
<keep-alive>
缓存组件把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染可以添加一个 keep-alive
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,主要用于保留组件状态或避免重新渲染- include(String/Regexp) : 指定缓存组件名
- exclude(String/Regexp) : 指定不缓存的组件名
<!-- 代表 xxx, yyy 下的组件被缓存 这里的 xxx 和 yyy 是组件名 该大写的大写 必须一致-->
<keep-alive include="xxx,yyy">
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
slot
Props:
name - string,用于命名插槽。
Usage:
< slot> 元素作为组件模板之中的内容分发插槽。< slot> 元素自身将被替换。
<!-- 1、具名插槽 -->
<base-layout>
<template v-slot:header>
Header content
</template>
Default slot content
<template v-slot:footer>
Footer content
</template>
</base-layout>
<!-- 2、接收 prop 的具名插槽 -->
<infinite-scroll>
<template v-slot:item="slotProps">
<div class="item">
{{ slotProps.item.text }}
</div>
</template>
</infinite-scroll>
<!-- 3、接收 prop 的默认插槽,使用了解构 -->
<mouse-position v-slot="{ x, y }">
Mouse position: {{ x }}, {{ y }}
</mouse-position>
利用组件内容进行通讯(父->子)
在组件模板中利用内置组件
<slot></slot>
来承载组件内容,否则它的内容都会被忽略(被模板内容覆盖)
-
默认插槽default
<!-- 使用组件 --> <nav-link url="/home">首页</nav-link> <!-- 定义组件 --> <script> Vue.component('nav-link',{ props:['url'] //以下template写法,组件内容“首页”,会被template的内容覆盖掉, //最终解析为:<a href="/home"><span>Home</span></a> //template:`<a :href="url"><span>Home</span></a>` // 解决方案:可以用<slot></slot>保留内容和设置默认值 // 最终解析为:<a href="/home">首页<span>Home</span></a> template:`<a :href="url"><slot></slot><span>Home</span></a>` }); </script>
-
具名插槽:
- 模板内容:给
<slot/>
组件命名(设置name属性) - 组件内容:设置slot属性,实现内容精准显示到模板具体位置
Vue2.6+已经废除slot属性,改成
v-slot:name
(只能用在template元素或组件上) - 模板内容:给
<!-- 组件模板内容 -->
<template id="myTest">
<div>
<slot name="header">这是拥有命名的slot的默认内容</slot>
<slot>这是拥有命名的slot的默认内容</slot>
<slot name="footer">这是拥有命名的slot的默认内容</slot>
</div>
</template>
<!-- 使用组件 -->
<my-component>
<span slot="header">这里的内容显示到name为header的插槽</span>
<span>这里的内容显示到默认插槽</span>
<span slot="footer">这里的内容显示到name为footer的插槽</span>
</my-component>
<!-- Vue2.6+用法 -->
<my-component>
<template v-slot:header>这里的内容显示到name为header的插槽</template>
<span>这里的内容显示到默认插槽</span>
<template v-slot:footer>这里的内容显示到name为footer的插槽</template>
</my-component>
作用域插槽(子- >父)
Vue编译规则:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译
利用作用域插槽(slot-scope)实现把组件模板template中的数据传到组件内容中处理,实现特殊定制(PS:Vue2.6+已废除该属性,改为
v-slot:name
格式,简写:#name)
<!-- mynav组件模板 -->
<div class="box">
<slot :msg="msg" :username="username">{{username}},{{msg}}</slot>
<slot name="footer" title="播放器" :player="player">{{player}}</slot>
</div>
<!-- 组件内容 -->
<mynav>
<!-- props为传过来的数据组成的对象 -->
<div slot-scope="props">{{props.msg}},{{props.username}}</div>
<!-- Vue2.6+用法 -->
<div v-slot:default="props">{{props.msg}},{{props.username}}</div>
<div v-slot:footer="foot">{{foot.title}},{{foot.player}}</div>
</mynav>
transition 和 transition-group
过渡动画
<transition>
<transition-group>
<transition>
用于单个元素动画,<transition-group>
用于多个元素并解析为一个标签(默认:span)
属性
-
name : 过渡类名前缀(默认:v)
如设置name=“fade”,过渡类名变成:fade-enter / fade-enter-active / fade-leave / fade-leave-active
-
css : boolean,是否使用 CSS 过渡类(默认:true)。设置为 false,将只通过组件事件触发注册的 JavaScript 钩子。
-
自定义过渡类名(可配合animate.css框架实现过渡效果)
- enter-class
- enter-active-class
- enter-to-class
- leave-class
- leave-active-class
- leave-to-class
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" > </transition>
触发动画场景
Vue会自动检测是否设置css动画或JavaScript钩子,并在下列情形中添加进入/离开过渡效果(css过渡或javascript过渡)
- 条件渲染 (使用 v-if)
- 条件展示 (使用 v-show)
- 动态组件
- 组件根节点
CSS过渡
-
通过CSS过渡类名
组件过渡过程中,默认会有四个CSS类名自动进行切换,会有如下四个CSS类名:
- v-enter:进入过渡的开始状态,元素被插入时生效,只应用一帧后立即删除;
- v-enter-active:进入过渡的结束状态,元素被插入时就生效,在过渡过程完成之后移除;
- v-leave:离开过渡的开始状态,元素被删除时触发,只应用一帧后立即删除;
- v-leave-active:离开过渡的结束状态,元素被删除时生效,离开过渡完成之后被删除;
JavaScript过渡
通过内置事件实现过渡动画效果,可以利用第三方动画库(如:velocity.js,jquery等)实现动画效果
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
</transition>
methods: {
// 过渡进入
// 设置过渡进入之前的组件状态
beforeEnter: function (el) {
// ...
},
// 设置过渡进入完成时的组件状态
enter: function (el, done) {
// ...
done()
},
// 设置过渡进入完成之后的组件状态
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// 过渡离开
// 设置过渡离开之前的组件状态
beforeLeave: function (el) {
// ...
},
// 设置过渡离开完成时地组件状态
leave: function (el, done) {
// ...
done()
},
// 设置过渡离开完成之后的组件状态
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// ...
}
}
代码解释如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.css">
<script src="../js/vue.js"></script>
<style>
/* 1、默认 v */
/*.v-enter,
.v-leave-to {
opacity: 0;
transition: all 1s;
}
.v-enter-to,
.v-leave {
opacity: 1;
transition: all 1s;
} */
/* 2、标签中添加一个name属性,然后把类名中v改成你定义的类名 */
.my-enter,
.my-leave-to {
opacity: 0;
transition: all 1s;
}
.my-enter-to,
.my-leave {
opacity: 1;
transition: all 1s;
}
</style>
</head>
<body>
<div id="app">
<!-- 1、动画效果 -->
<!-- <button @click="tag">点我看效果</button>
<transition>
<div v-if="flag">我是div,会消失和隐藏</div>
</transition> -->
<!-- 2、动画效果 -->
<button @click="tag">点我看效果</button>
<!-- 需要在transition标签上添加一个name属性,然后把类名中v改成你定义的类名, 比如my -->
<transition name="my">
<div v-if="flag">我是div,会消失和隐藏</div>
</transition>
</div>
<script>
// 点击反转flag的值
const vm = new Vue({
el: '#app',
data: {
flag: true
},
methods: {
tag() {
this.flag = !this.flag
}
}
})
</script>
</body>
</html>
注意点
以上内置组件不会产生具体的html结构;