内容:计算属性、过滤器、过渡动画、组件
生命周期、vue-cli脚手架和组件传值
一、计算属性
1.基本使用
computed,当我们的页面上需要频繁地进行数据运算时,我们需要用到计算属性。
(1)计算属性的变量名可以不在data中定义
(2)计算属性的业务逻辑函数只有在挂载点内被使用之后,才会触发
(3)计算属性关联的数据发生变化之后,计算属性的逻辑函数会重新执行,得到新的结果。
2.计算属性和methods的区别
计算属性:当关联的数据没有发生变化时,会优先使用数据缓存
而methods,只要调用了,那么就会重新执行指定的函数。
3.计算属性和监听的区别
(1)在页面加载时,计算属性的逻辑函数,在挂载点内使用了计算属性的变量时,会自动的触发,但是监听的逻辑函数不会自动执行
(2)当监听和计算属性关联的数据发生改变时,监听的优先级要比计算属性要高。
(3)计算属性:当关联的数据没有发生变化时,会优先使用数据缓存,监听没有数据缓存。
购物车案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车</title>
<script src="./js/vue.js"></script>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
img{
width: 100px;
height:100px;
}
</style>
</head>
<body>
<div id="app" class="container">
<h2 class="text-center">购物车</h2>
<table class="table table-bordered table-hover" style="width:1000px;">
<thead>
<tr>
<th>#</th>
<th>商品名称</th>
<th>商品图片</th>
<th>价格</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) of goods">
<td>
<input type="checkbox" v-model="item.checked">
</td>
<td>{{ item.title }}</td>
<td>
<img :src="item.img">
</td>
<td>{{ item.price }}</td>
<td>
<button @click="minus(index)">-</button>
{{ item.num }}
<button @click="add(index)">+</button>
</td>
<td>{{ (item.price * item.num).toFixed(2) }}</td>
<td>
<button @click="del(index)" class="btn btn-danger">删除</button>
</td>
</tr>
<tr>
<td>
全选:<input type="checkbox" v-model="allChecked"/>
</td>
<td colspan="6">总价:{{ allPrice }}</td>
</tr>
</tbody>
</table>
</div>
<script>
new Vue({
el:"#app",
data:{
allChecked:false,
goods:[
{
title:"【春节放价】【预售】Web前端在线系统升级课",
price:2399,
num:1,
img:"http://xue.ujiuye.com/uploads_it/1912/QuanGuo/ECK360449855TTKM.jpg",
checked:true
},
{
title:"【春节放价】Web小程序开发从0-1",
price:79.2,
num:90,
img:"http://xue.ujiuye.com/uploads_it/1911/QuanGuo/EBL274695946BHSZ.jpg",
checked:false
},
{
title:"【春节放价】Web前端基础与小程序开发",
price:319.2,
num:1,
img:"http://xue.ujiuye.com/uploads_it/1911/QuanGuo/EBL1175977182TNT.jpg",
checked:true
}
]
},
methods:{
//数量增加
add(n){
if(this.goods[n].num<99){
this.goods[n].num++;
}
},
//数量减少
minus(m){
if(this.goods[m].num>1){
this.goods[m].num--;
}
},
del(j){
//删除
this.goods.splice(j,1)
}
},
computed:{
allPrice(){
console.log('计算属性执行了')
var sum = 0;
// map 遍历数组
this.goods.map(d=>{
// 把选中商品的单价乘以数量进行累加
if(d.checked){
sum += d.price * d.num
}
});
//every 如果整个数组的所有元素的值都为true,那么结果就为true,只要有一个元素的值为false,那么结果就为false
this.allChecked = this.goods.every(d=>{
return d.checked;
})
return sum.toFixed(2);
}
},
//监听全选变量的值
watch:{
allChecked:function(newVal,oldVal){
console.log('监听被执行了')
//遍历所有的商品,把每个商品的选中状态和全选的状态进行同步
this.goods.map(d=>{
d.checked = newVal;
})
}
}
})
</script>
</body>
</html>
二、过滤器
作用:对页面中展示的数据进行处理
定义:
(1)全局定义
(2)局部定义
语法格式:
new Vue({
el
data
filters:{
过滤器名称(形参){
...
return 结果
}
}
})
使用:
通过 变量值 | (管道符) 过滤器名称
1000 | formatPrice(形参2)
参数:
管道符左边的变量永远是第一个参数,管道符右边过滤器名称(参数),作为第二个参数。
三、过渡动画
使用场景:标签显示/隐藏、存在/消失、动态组件
1.内置类名
匿名使用
(1)进入时状态
.v-enter 设置元素进入开始状态
.v-enter-active 设置元素进入中的状态
.v-enter-to 设置元素进入后的状态
(2)离开时状态
.v-leave 设置元素离开开始状态
.v-leave-active 设置元素离开中的状态
.v-leavt-to 设置元素离开结束的状态
命名使用
当页面上有很多个元素需要去设置不同的动画过渡效果时,可以给transtion标签增一个name属性来进行区分。
2.结合animate.css
(1)下载animate.css
(2)给需要添加动画过渡效果的标签增加一个父级标签<transition>
(3)给transition设置两个属性
enter-active-class 元素进入时的动画效果
leave-active-class 元素离开时的动画效果
四、组件【重点】
1.介绍
组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树。
组件是vue的一个实例,所以vue实例拥有的选项(除了el)组件都可以拥有【重点】
2.定义
语法格式:
new Vue({
el:"#app",
components:{
组件名称:{
template:"模板内容"
}
}
})
注意事项:
(1)组件名称不能是系统内置的标签名,比如:div、img
(2)template模板内容中只能有一个根标签
(3)template属性对应的值可以是一段html字符串,也可以是一个id选择器
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<my-div></my-div>
<first></first>
<second></second>
</div>
<!-- template标签不会被浏览器解析 -->
<template id="second">
<div>
<h2>second组件</h2>
</div>
</template>
<script>
new Vue({
el:"#app",
components:{
myDiv:{
template:"<div><div>这是一个自定义组件</div><h1>哈哈</h1></div>"
},
first:{
template:`
<div>
<h1>这是first组件</h1>
</div>
`
},
second:{
template:"#second"
}
}
})
</script>
</body>
</html>
3.组件定义优化
因为template属性的值是一个对象,所以可以把这个对象在实例化vue之前定义好,这样的话在注册组件时,代码编写就非常简洁。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件定义优化</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<v-one></v-one>
<v-two></v-two>
<v-three></v-three>
{{ msg }}
</div>
<!-- template标签不会被浏览器解析 -->
<template id="one">
<div>
<h1>这是第一个组件{{ msg }}</h1>
</div>
</template>
<template id="two">
<div>
<h1>这是第二个组件</h1>
<h3>{{msg}}</h3>
</div>
</template>
<template id="three">
<div>
<h1>这是第三个组件</h1>
</div>
</template>
<script>
var vOne = {
template:'#one',
data(){
return{
msg:'这是第一个组件的数据'
}
},
methods:{}
};
var vTwo = {
template:'#two',
data(){
return{
msg:'这是第二个组件的数据'
}
}
};
var vThree = { template:'#three' };
new Vue({
el:"#app",
// 注册组件
components:{
// vOne:one
vOne,vTwo,vThree
},
data:{
msg:'哈哈'
}
})
</script>
</body>
</html>
4.组件中data为什么是一个函数【面试题】
因为普通的数据定义方式是一个对象,所以对象中的数据一旦发生变化,那么在页面中使用过这个数据的地方都会发生相应的改变。
而组件是可以重复使用的,所以在组件中定义data时不应该是一个对象,而应该是一个函数,在函数中返回一个新的对象,这样的话组件与组件之间就不会产生数据的影响。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件中的data应该是一个函数</title>
<script src="./js/vue.js"></script>
</head>
<body>
<!-- <div id="app">
<p>{{ count }}</p><button @click="count++">点击</button>
<br>
<p>{{ count }}</p><button @click="count++">点击</button>
<br>
<p>{{ count }}</p><button @click="count++">点击</button>
<br>
</div>
<script>
new Vue({
el:"#app",
data:{
count:1
}
})
</script> -->
<div id="app">
<v-one></v-one>
<v-one></v-one>
</div>
<template id="one">
<div>
<p>{{ count }}</p>
<button @click="count++">点击</button>
</div>
</template>
<script>
var vOne = {
template:"#one",
data(){
return{
count:1
}
}
}
new Vue({
el:"#app",
components:{
vOne
}
})
</script>
</body>
</html>
5.组件后台管理系统页面布局案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>后台管理系统系统页面布局</title>
<script src="./js/vue.js"></script>
<style>
*{margin:0;padding:0}
html,body,#app{
width:100%;
height: 100%;
}
#app{
display:flex;
flex-direction: column;
}
.header{
height:50px;
background-color: bisque;
}
.main{
flex:1;
display: flex;
}
.left{
width:150px;
background-color: deepskyblue;
}
.left ul{
text-align: center;
}
.left ul li{
margin:20px;
list-style: none;
font-size:20px;
color:#fff;
}
.right{
background-color: gainsboro;
flex:1
}
.footer{
height: 40px;
background-color: cornflowerblue;
}
</style>
</head>
<body>
<div id="app">
<v-header></v-header>
<v-main class="main"></v-main>
<v-footer class="footer"></v-footer>
</div>
<template id="header">
<div class="header">
<p>XXX信息管理系统</p>
</div>
</template>
<template id="main">
<div>
<v-left class="left"></v-left>
<v-right class="right"></v-right>
</div>
</template>
<template id="footer">
<div>
<h1>这是footer组件</h1>
</div>
</template>
<template id="left">
<div>
<ul>
<li>学生管理</li>
<li>教师管理</li>
</ul>
</div>
</template>
<template id="right">
<div>
<h1>这是右侧组件</h1>
</div>
</template>
<script>
var vHeader = {
template:"#header"
}
var vLeft = {
template:"#left"
}
var vRight = {
template:"#right"
}
var vMain = {
template:"#main",
components:{
vLeft,vRight
}
}
var vFooter = {
template:"#footer"
}
new Vue({
el:"#app",
components:{
vHeader,vMain,vFooter
}
})
</script>
</body>
</html>
作业:
1.实现购物车案例
2.实现后台管理系统页面布局