复习
- let vm=new Vue()
vm=viewModel 数据最终都会被vm代理 - {{msg}} 表达式,赋值,计算,三元,尽量少写逻辑
- 试图控制数据
input,checkbox,textarea,radio,select
但是selected, value,checked都无效了 - 指令 必须v-开头
- v-text 相当于{{}}
- v-once 只绑定第一次的数据
- v-html渲染html
- v-if 根据表达式,决定是否插入页面元素
- v-for 循环
- 对象
要给存在的属性赋值
增加属性:vm.$set(vm.a,"school",1)
或者直接替换 - 数组
要利用变异方法改变页面显示的数组 - 时间
v-on:事件名称="" 或者@事件名称=""
事件放在methods
checkbox
只有一个复选框的时候,vm会自动把数据变为布尔值传递给checkbox
<input type="checkbox" v-model="a">
当需要多选的时候,可以将数据定义为数组类型,增添value属性
选中时添加新的value,取消选择,则减少相应的项
<div id="app">
<input type="checkbox" v-model="a" value="大白熊">大白熊
<input type="checkbox" v-model="a" value="狼">狼
<input type="checkbox" v-model="a" value="猫">猫
{{a}}
<!--这里输出的a为一个数组,选中时添加新的value,取消选择,则减少相应的-->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm=new Vue(
{ el:"#app",
data:{a:[]}})
页面不闪烁{{}}
在div中添加v-cloak属性,并在CSS中添加
[v-cloak]:{display:none}
页面渲染完后才会显示所有内容,渲染前的{{msg}}并不会显示
VueTools
根实例就是 let vm=new Vue()创建的这个VM
直接在chrome商店可以下载,要翻墙
避免console.log()
今天主要任务是利用vue建立一个购物车界面
axios
是基于promise的调用发送ajax的方法
引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
在VM中需要一个created(){}
- 这个方法是在数据初始化之后调用的,this是指向VM实例的
- 除了data中的数据,methods中的数据也能拿到
- 钩子函数
axios.get().then()
因为是基于promise的,先来复习一下promise,有两个回调函数,一个是调用成功执行,一个是调用失败执行
var promise1=new Promise(function(resolve,rejuct)
{
resolve("大白熊")
console.log("执行")
})
console.log("尾巴")
promise1.then(
function(str)
{
console.log(str+"1")
return str
},
function(err)
{
alert("失败了")
}
)
这个程序最终的结果是
执行
尾巴
大白熊1
可以看出定义Promise的时候立刻执行括号中的函数,然后依次向下执行
有几点需要注意
- get的回调函数如果不用箭头函数的形式,this是指向windows
- chrome浏览器不支持跨域传递数据,本地ajax想要执行,必须在属性 目标最后加上 --allow-file-access-from-files
created(){
//在数据被初始化后调用
//在这个例子中就是products,this指向VM实例
//钩子函数
//也可以拿到method中的方法
//专门用来发送ajax的方法
axios.get("./pro.json").then(
data=>{this.products=data.data},
//这里不能回调函数中this,回调函数的this指向window
//但是箭头函数的this指向的是实例
//在chrome浏览器属性 目标那里最后加上 --allow-file-access-from-files 否则不能本地ajax
err=>{alert("失败了")})
//基于promise的
},
现在成功将products的数据传递过来了
Bootstrap
引入
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
栅格化布局,默认12列,有一些框架可能是24列
常见样式:基本样式+增强样式
后面专门来学习一下
购物车界面
首先需要将页面的几个部分确认:
table
<div class="container">
<!--每一行又会拥有12列-->
<div class="row">
<table class="table table-hover table-bordered">
<caption style="font-size:40px;text-align:center;" class="text-success">购物车</caption>
<tr>
<th>全选<input type="checkbox"></th>
<td>商品名称</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
<td>操作</td>
</tr>
<tr>
<td><input type="checkbox" ></td>
<td><img></td>
<td></td>
<td></td>
<td></td>
<td><button class="btn btn-danger" style="text-size:20px;">删除</button></td>
</tr>
<tr>
<td colspan="6" style="text-align:right;font-size:20px">总价:</td>
</tr>
</table>
</div>
</div>
全选框与每个物品的选框
全选框与物品选框的逻辑
- 选中全选框时,对应的全部物品isselected变为相应的false或true
- 有一件物品没有被选中的时候,全选框为false
- 全部物品被选中时,全选框为false
为了完成这一点,全选框与每个物品选框都要有方法
首先在vm中定义check数据
然后HTML中
这里要用change事件,因为click点击时,checkbox状态还没有改变,所以拿到的是相反的,change保证只当值变化的时候执行函数
<th>全选<input type="checkbox" v-model="check" v-on:change="checkAll()"></th>
然后在methods中定义checkAll方法
checkAll(){
this.products.forEach((item)=>{item.isselected=this.check;})
}
现在反过来用每个物品的选框控制全选框,这里要用到arr.every(function(item){}),只有全部item都满足要求的时候返回true
HTML中
<td><input type="checkbox" v-model="product.isselected" @change="change">
methods中
change(){
this.check=this.products.every(item=>item.isselected)
}
商品图片
v-bind
不能直接src="product.producteImg"
在属性中取值需要利用v-bind
v-bind:src=""
或者缩写为
:src=""
<td><img style="margin-left:30px" width="100px" height="100px" :src="product.producteImg" :title="product.productName" >{{product.productName}}</td>
单价与总价
filter(){}
在VM中可以定义filter()这样的钩子函数用于过滤数据
过滤器 原数据不变的情况下 只是改变显示的效果
管道符|
filters:{//可以有好多自定义过滤器
toFixed(input,parma){//这里的this是window
return '¥'+input.toFixed(parma);
}
}
HTML中
<td>{{product.productPrice | toFixed(2)}}</td>
<td>{{product.productCount*product.productPrice | toFixed(2)}}</td>
数量
数量只能是数字,所以定义type为number
为了能够让products中的属性值也是数字而非字符串,需要v.model.number也可以v.model.number.lazy
.number是让输入框的值变成数字类型,lazy当输入框失去焦点的时候更新
删除
与前文中列表删除并没有任何不同
HTML中
<td><button class="btn btn-danger" style="text-size:20px;" v-on:click="del(index)">删除</button></td>
VM中
del(ind){
this.products=this.products.filter((item,index)=>ind!=index)
}
也可以不用index而用每个项的地址来进行过滤
总价
{{}}中除了放数据,也可以放方法,每一次页面更新,都会调用方法改变值,所以这里我们在HTML中加入
<tr>
<td colspan="6" style="text-align:right;font-size:20px">总价:{{sumall() | toFixed(2)}}</td>
</tr>
然后再methods中加入
sumall(){
selectproducts=this.products.filter(item=>item.isselected)
return selectproducts.reduce((prev,next)=>{ return prev+next.productCount*next.productPrice;},0)
}
全部的程序在
https://www.jianshu.com/p/d45bb90d6fa8
computed
在以上的程序中有几个问题
1.数据一变化就会重新调用sumall函数,不会缓存结果,哪怕变化的数据对于sumall()没有用
2.删除不会影响全选框
为了解决这些问题,引入computed,放在computed中最后也会放在VM中,所以不能和methods和data重名
computed使得依赖的数据没有变化的时候就不会执行get()函数
与Object.defineProperty类似
全选框变动
首先删掉data中的checkAll,在computed中加入checkAll
HTML中更改为
<th>全选<input type="checkbox" v-model="checkAll"></th>
这里调用checkAll的时候会调用checkAll的get函数
当从页面中给checkAll赋值的时候,会调用set函数
computed:{
//放在computed中最后也会放在vm上,不能喝methods和data重名
checkAll:{
get(){
//this依旧指向实例 默认v-model会获取checkAll的值,所以会调用get方法
//放product值会重新计算
return this.products.every(item=>item.isselected)
},
set(val){
//当我们给checkbox赋值的时候
this.products.forEach((item)=>{item.isselected=val;})
}
}}
计算总价格
<td colspan="6" style="text-align:right;font-size:20px">总价:{{sumall | toFixed(2)}}</td>
这里没有赋值,所以不会调用set,可以简写为
sumall(){}
相当于只调用get函数
sumall:{
//如果计算属性写成函数,默认调用get方法
get(){
//如果依赖的数据没有变化就不会重新执行
selectproducts=this.products.filter(item=>item.isselected)
return selectproducts.reduce((prev,next)=>{ return prev+next.productCount*next.productPrice;},0)
},
set(){}
}
全部代码在https://www.jianshu.com/p/898e623da754
动画
v-show和v-if
- 两者都可以控制显示与不显示
- if操作的是dom show操作的是样式
- 如果频繁的切换dom使用v-show,当数据一开始就确定会是true或者false不会改变的时候使用v-if
只有dom从显示到隐藏或者隐藏到显示,才能使用vue的动画
使用vue动画时,将需要变化的部分用transition组件框起来
动画中的几种状态
这里fada是transition的名字
- 进入过渡的开始状态
.fade-enter{} - 进入过渡的结束状态
.fade-enter-to{} - 动画生效时的状态
.fade-enter-active{} - 离开过渡的开始状态,在离开过渡被触发时立刻生效
.fade-leave{} - 离开过渡的结束状态
.fade-leave-to{} - 离开过渡生效时的状态,在整个离开过渡的阶段中应用
.fade-leave-active{}
两个变化生效的状态括号中的定义应该是
.fade-enter-active{transition:opactity 1s linear}
/*transition:希望的变化或者函数 时间 变化方式*/
这里的变化函数可以使用CSS中的@keyframe
简单的进入离开动画
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<style>
.fade-enter{opacity:0}
/*进入过渡的开始状态*/
.fade-enter-to{opacity:0.5}
/*进入过渡的结束状态*/
.fade-enter-active{transition:opacity 1s linear}
/*进入过渡生效时的状态*/
/*不定义只有一个的时候可以用v-*/
.fade-leave{opacity:0.5}
/*离开过渡的开始状态,在离开过渡被触发时立刻生效*/
.fade-leave-to{opacity:0}
/*离开过渡的结束状态*/
.fade-leave-active{transition:opacity 1s linear}
/*离开过渡生效时的状态状态,在整个离开过渡的阶段中应用*/
</style>
</head>
<body>
<div id="app">
<!--v-if v-show if操作的是dom show操作的是样式-->
<!--如果频繁的切换dom使用v-show,当数据一开始就确定会是true或者false不会改变的时候使用v-if-->
<!--只有dom从显示到隐藏或者隐藏到显示,才能使用vue的动画-->
<button @click="flag=!flag">切换</button>
<transition name="fade">
<!--vue的组件-->
<div v-show="flag" id="bear">大白熊</div>
</transition>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm=new Vue({
el:"#app",
data:{
flag:false
}
})
</script>
</body>
</html>
明天专门研究下好了