正课:
- 绑定样式:
- 自定义指令
- 计算属性
- 过滤器
- axios
- 生命周期
- 组件
一. 绑定样式:
- 绑定内联样式:
(1). 不好的做法: 将style属性看做一个普通的字符串属性进行绑定。
a.
<元素 :style="变量">
data:{
变量: "css属性:值; css属性:值;..."
}
b. 问题: 极其不便于只操作其中某一个css属性
(2). 好的办法: 将style看做一个对象来绑定。每个css属性都是对象中的一个属性。
结果: "css属性1:属性值1; css属性2:属性值2;..."
↑ ↑ ↑ ↑
a.
<元素 :style="{ css属性1: 变量1, css属性2: 变量2, ... }"
data:{
变量1:"属性值1",
变量2:"属性值2",
... ...
}
b. 优点: 轻易只修改其中某一个css属性值,而不影响其他属性值
c. 问题: 如果多个css属性的变量零散的保存在data中,如果多个元素都需要控制内联样式,就极容易发生冲突。
d. 示例: 控制一个飞机的飞行
1_style.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<style>
img{
position:fixed;
left:50%;
}
</style>
</head>
<body>
<div id="app">
<!-- 属性名 变量-->
<!-- 不能自定义 可自定义-->
<!-- <img :style="{marginLeft:marginLeft,bottom:bottom}" src="img/p3.png"> -->
<img :style="{marginLeft,bottom}" src="img/p3.png">
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
marginLeft:"-100px", //必须带单位
bottom:"50px"
}
})
</script>
</body>
</html>
(3). 更好的解决办法: 将每个元素所需的所有内联样式变量,集中保存在data中的一个对象里。
a.
<元素1 :style="变量名1">
<元素2 :style="变量名2">
data:{
变量名1:{
css属性:值,
... : ...
},
变量名2:{
css属性:值,
... : ...
}
b. 优点: 避免不同元素间相同css属性的冲突
c. 示例: 控制两个飞机的飞行
1_style2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<style>
img{
position:fixed;
left:50%;
}
</style>
</head>
<body>
<div id="app">
<img :style="img1Style" src="img/p3.png">
<img :style="img2Style" src="img/p5.png">
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
img1Style:{
marginLeft:"-200px",
bottom:"25px",
},
img2Style:{
marginLeft:"100px",
bottom:"100px"
}
}
})
</script>
</body>
</html>
(4). 问题: 如果元素上有些内联css属性是固定不变的,而有些css属性是可能发生变化的?
(5). 解决: 其实在一个元素上写死的固定不变的style和动态变化的:style是可以并存的。最后运行的结果是,:style动态生成的css属性会和style中固定不变的属性合并为最终应用到元素上的style属性。
结果: style="固定不变的css属性:值; 变化的css属性: 值; ..."
↑ ↑
<元素 style="固定不变的css属性:值" :style="变量"
data:{
变量:{
变化的css属性: 值
}
}
比如: <img style="left:50%" :style="img1Style" src="img/p3.png">
data:{
img1Style:{
marginLeft:"-200px",
bottom:"25px",
}
}
(6). 问题: DOM中经常批量修改一个元素的多个css属性,如果单个修改每个css属性值,代码会很繁琐
(7). 解决: 用class来代替单独修改每个css属性。
- 绑定class:
(1). 不好的方法: 将整个class字符串,看做一个普通的字符串属性绑定.
<元素 :class="变量">
data:{
变量: "class1 class2 ..."
}
缺点: 极其不便于修改其中某一个class
(2). 好的方法: 将class看做一个对象来绑定。
a. <元素 :class="{ class1: 变量1, class2: 变量2, ... }"
data:{
变量1: true或false,
变量2: true或false,
... : ...
}
说明: 当一个class对应的变量值是true,则这个class会出现在编译后的元素上,起作用;当一个class对应的变量值为false,则这个class不会出现在编译后的元素上,不起作用!
b. 优点: 极其便于修改其中某一个class
c. 示例: 验证手机号
2_class.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<style>
.span-cls{
padding:5px 10px;
}
.success{
background-color:lightGreen;
border:green;
color:green;
}
.fail{
background-color:pink;
border:red;
color:red;
}
</style>
</head>
<body>
<!--1. 做界面
1.1 找界面中可能发生变化的位置
本例中:
文本框会被用户主动修改,新值要自动更新到程序中,所以文本框用v-model绑定
span的样式可能发生变化,在success和fail两种class之间来回切换
span的内容可能发生变化
1.2 找界面中触发事件的元素
本例中: 文本框失去焦点时自动触发验证-->
<div id="app">
手机号:<input v-model="phone" @blur="vali">
<!-- <span class="span-cls" :class="{ success:success, fail:fail }">{{msg}}</span> -->
<span class="span-cls" :class="{ success, fail }">{{msg}}</span>
</div>
<script>
//2. 创建new Vue()对象
var vm=new Vue({
el:"#app",
//3. 创建模型对象
//因为界面中共需要4个变量,所以:
data:{
phone:"",
success:false,
fail:false,
msg:""
},
//因为界面中需要一个事件处理函数
methods:{
vali(){
//定义验证手机号的正则表达式:
var reg=/^1[3-9]\d{9}$/;
//用正则验证手机号正确
// 复习小程序中js高级第2天
if(reg.test(this.phone)==true){
//就修改span为验证通过的样子
this.success=true;
this.fail=false;
this.msg=" √ 手机号格式正确";
}else{//否则如果验证失败
//就修改span为验证失败的样式
this.success=false;
this.fail=true;
this.msg=" × 手机号格式不正确"
}
}
}
})
</script>
</body>
</html>
d. 问题: 如果多个元素都需要用同一个class,但是启用和禁用的状态各不相同,如果将变量直接保存在data中,极容易发生冲突
(3). 更好的方法: 将一个元素的多个class包裹在一个对象变量中:
a.
<元素1 :class=变量1">
<元素2 :class=变量2">
data:{
变量1:{
class名: true或false,
... : ...
},
变量2:{
class名: true或false,
... : ...
}
}
b. 优点: 即使多个元素,共用同一个class,也不会发生冲突!
c. 示例: 验证手机号和身份证号
2_class3.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<style>
.span-cls{
padding:5px 10px;
}
.success{
background-color:lightGreen;
border:green;
color:green;
}
.fail{
background-color:pink;
border:red;
color:red;
}
</style>
</head>
<body>
<!--1. 做界面
1.1 找界面中可能发生变化的位置
本例中:
文本框会被用户主动修改,新值要自动更新到程序中,所以文本框用v-model绑定
span的样式可能发生变化,在success和fail两种class之间来回切换
span的内容可能发生变化
1.2 找界面中触发事件的元素
本例中: 文本框失去焦点时自动触发验证-->
<div id="app">
手机号:<input v-model="phone" @blur="valiPhone">
<span class="span-cls" :class="phoneSpan">{{phoneMsg}}</span><br/>
身份证号:<input v-model="pid" @blur="valiPid">
<span class="span-cls" :class="pidSpan">{{pidMsg}}</span>
</div>
<script>
//2. 创建new Vue()对象
var vm=new Vue({
el:"#app",
//3. 创建模型对象
//因为界面中共需要4个变量,所以:
data:{
phone:"",//接文本框中的值
pid:"",//接文本框中的值
phoneSpan:{//控制手机号验证结果的样式
success:false,
fail:false
},
pidSpan:{//控制身份证号验证结果的样式
success:false,
fail:false
},
phoneMsg:"",//保存手机号的错误提示
pidMsg:""//保存身份证号的错误提示
},
//因为界面中需要一个事件处理函数
methods:{
valiPhone(){
//定义验证手机号的正则表达式:
var reg=/^1[3-9]\d{9}$/;
//用正则验证手机号正确
// 复习小程序中js高级第2天
if(reg.test(this.phone)==true){
//就修改span为验证通过的样子
this.phoneSpan={
success:true,
fail:false
};
this.phoneMsg=" √ 手机号格式正确";
}else{//否则如果验证失败
//就修改span为验证失败的样式
this.phoneSpan={
success:false,
fail:true
};
this.phoneMsg=" × 手机号格式不正确"
}
},
valiPid(){
//定义验证身份证号的正则表达式:
var reg=/^\d{15}(\d\d[0-9x])$/i;
//用正则验证身份证号正确
// 复习小程序中js高级第2天
if(reg.test(this.pid)==true){
//就修改span为验证通过的样子
this.pidSpan={
success:true,
fail:false
};
this.pidMsg=" √ 身份证号格式正确";
}else{//否则如果验证失败
//就修改span为验证失败的样式
this.pidSpan={
success:false,
fail:true
};
this.pidMsg=" × 身份证号格式不正确"
}
}
}
})
</script>
</body>
</html>
(4). 问题: 如果元素上有些class是固定不变的,而有些class是可能发生变化的?
(5). 解决: 其实在一个元素上写死的固定不变的class和动态变化的:class是可以并存的。最后运行的结果是,:class动态生成的class字符串会和class中固定不变的class字符串合并为最终应用到元素上的class属性。
二. 自定义指令:
- 问题: 希望在页面加载完之后,自动给元素执行一些初始化的DOM操作。但是,在vue中几乎没有提供任何查找办法!我们就找不到DOM元素,就无法执行任何DOM相关的操作
- 解决: 今后,只要在页面加载完之后,希望对元素执行一些初始化的DOM操作,比如: 让元素自动获得焦点,都用自定义指令。
- 如何: 2步
(1). 定义自定义指令:
指令
Vue.directive("自定义指令名",{//指令名: 千万不要加v-开头!
//回调函数: 当new Vue()将当前元素添加页面上之后,自动执行。
//自动将当前带有该指令的元素对象传给回调函数的形参
//插入后 ↓
inserted(domElem){
对当前带有这个自定义指令的DOM元素,自动执行DOM操作。
}
})
(2). 使用自定义指令: 将自定义指令添加到DOM元素上
<元素 v-自定义指令名>
强调: 虽然定义自定义指令时,不能加v-前缀。但是使用自定义指令时,必须加v-前缀的!
- 原理:
(1). Vue.directive(),创建一个新指令,并保存到Vue大家庭中备用。
(2). new Vue()扫描到带有这个指令的元素时,自动执行其中的inserted(),并自动将当前带有这个指令的DOM元素传给inserted()函数的形参。
(3). 在inserted()回调函数内,可以对当前带有这个指令的元素执行任意原生的DOM操作! - 自定义指令名: 不要用驼峰命名,应该一律小写,并且用-分割多个单词
(1). 原因: 整个HTML语法不区分大小写的!
比如: 对于HTML来说: MyFocus 和myfocus 和myFocus是一样的!无法区分!
(2). 所以: 今后,凡是要用在HTML中的名称,都不能用驼峰命名!必须用-分割多个单词! - 示例: 自定义指令,让当前元素自动获得焦点:
3_directive.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<input v-my-focus><button>百度一下</button>
</div>
<script>
//1. 创建一个可让当前元素自动获得焦点的自定义指令
Vue.directive("my-focus",{
//当当前元素被加入到DOM树之后,立刻自动执行该函数
//并将当前元素自动传给domElem形参
inserted(domElem){
//对当前元素执行DOM操作: 自动获得焦点
domElem.focus();//复习DOM第4天
}
});
new Vue({
el:"#app"
})
</script>
</body>
</html>
三. 计算属性:
对应小程序视频: 小程序->在线->VUE->day03 2. 计算属性
- 问题: 页面上需要绑定一个值,但是这个值不是现成的!需要根据其他变量的值,经过复杂的计算(分支和循环)才能计算出来。
- 解决: 今后只要页面上需要一个值,但是这个值必须经过复杂计算才能得到,都用计算属性!
- 如何: 2步:
(1). 定义计算属性:
new Vue({
el:"#app",
data:{ ... },
methods:{ ... },
watch:{ ... },
//计算后的
computed:{
属性名(){ //但是本质却是一个函数
//根据其他变量的值,经过复杂计算,得出一个结果。
return 计算结果
}
}
})
(2). 使用计算属性:
<元素>xxxx{{属性名}}xxxx</元素>
强调: 使用计算属性时,一定不要加()
-
问题: computed vs methods
(1). methods的执行结果不会被vue缓存,每调用一次,就会重复计算一次!——没必要的,效率低!
(2). computed的执行结果会被vue缓存,反复使用,重复计算。除非计算属性所依赖的其它变量值发生了改变,vue才会自动重新计算计算属性的新值,重新缓存起来反复使用。 -
总结:
(1). 如果更侧重于使用一个函数的执行结果值时,首选computed。比如: 在页面上显示总价
(2). 如果更侧重于执行一个操作,不太关心具体的结果值时,首选methods。比如: 发送ajax请求 -
示例: 显示订单总价:
4_computed.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h3>总价: ¥{{total.toFixed(2)}}</h3>
<ul>
<li v-for="(p,i) of cart" :key="i">
{{p.pid}} || {{p.pname}} || ¥{{p.price.toFixed(2)}} || {{p.count}} || 小计:¥{{(p.price*p.count).toFixed(2)}}
</li>
</ul>
<h3>总价: ¥{{total.toFixed(2)}}</h3>
</div>
<script>
new Vue({
el:"#app",
data:{
cart:[
{pid:1, pname:"华为",price:5888, count:2},
{pid:2, pname:"苹果",price:9888, count:1},
{pid:3, pname:"小米",price:3888, count:3},
]
},
methods:{
},
computed:{
total(){
console.log(`执行了一次遍历和求和的操作`)
var result=0;
for(var p of this.cart){
result+=p.price*p.count;
}
return result;
}
}
})
</script>
</body>
</html>
四. 过滤器:
对应小程序视频: 小程序->在线->VUE->day03 3. 过滤器
-
问题: 有些数据不能直接给人看,需要先加工之后,再给人看。但是,又不愿意每次使用这种数据时,都把加工的过程重新写一遍!——繁琐
-
解决: 今后实际项目中,只要一个数据,不能直接给人看,需要先加工再显示时,都用过滤器。
-
如何: 2步
(1). 定义过滤器:
↓
Vue.filter(“过滤器名”, function(形参){
← return 返回值
})
(2). 使用过滤器:
<元素>{{变量 | 过滤器名 }}</元素> -
原理:
(1). Vue.filter()创建一个过滤器,保存到内存中vue大家庭中备用。
(2). 当new Vue()扫描到带有过滤器的元素时,就会去Vue大家庭中找是否包含想用的过滤器。
(3). 如果找到同名的过滤器,就自动调用过滤器函数,同时:
a. 自动传入|前的变量的原始值
b. 在过滤器函数内,经过加工后,返回新值
(4). new Vue()就会把过滤后返回的新值,显示在元素内容中 -
过滤器命名: 因为过滤器名是写在HTML中的{{}}内部,属于js的地盘。所以,过滤器名不能用-分割多个单词,应该用驼峰命名。
<h3>性别:{{sex | sexFilter}}</h3>
- 示例: 使用过滤器过滤性别:
5_filter.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!--HTML | js | HTML-->
<h3>性别:{{sex | sexFilter}}</h3>
</div>
<script>
//1. 创建过滤器
Vue.filter("sexFilter",function(oldVal){
return oldVal==1?"男":"女"
});
new Vue({
el:"#app",
data:{
sex:0
}
})
</script>
</body>
</html>
运行结果:
性别:女
- 过滤器传参: 2步:
(1). 定义过滤器时:
变量的原始值
预留
↓
Vue.filter("过滤器名",function(oldVal, 自定义形参,...){
return 返回值
})
(2). 使用过滤器时:
<元素>{{变量 | 过滤器名(实参值) }}</元素>
(3). 示例: 根据不同实参值,过滤不同语言的性别
5_filter2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h3>性别:{{sex | sexFilter}}</h3>
<h3>性别:{{sex | sexFilter("en")}}</h3>
</div>
<script>
//1. 创建过滤器
// "en","cn"
// ↓ ↓
Vue.filter("sexFilter",function(oldVal,yuyan){
if(yuyan=="en"){
return oldVal==1?"Male":"Female"
}else{
return oldVal==1?"男":"女"
}
});
new Vue({
el:"#app",
data:{
sex:1
}
})
</script>
</body>
</html>
运行结果:
性别:男
性别:Male
-
多个过滤器连用:
(1). <元素>{{变量 | 过滤器1 | 过滤器2 | … }}
(2). 强调:
a. 定义后一个过滤器时,充分考虑所有可能的传入的值。
b. 后一个过滤器不能只return新值,应该将新值和旧值合并返回。
(3). 示例: 过滤性别,即显示性别名,又显示性别图标:
5_filter3.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h3>性别:{{sex | sexIcon }}</h3>
<h3>性别:{{sex | sexFilter | sexIcon}}</h3>
<h3>性别:{{sex | sexFilter("en") | sexIcon}}</h3>
</div>
<script>
// 1,0,男,女,Male,Female
// \ /
Vue.filter("sexIcon",function(oldVal){
if(oldVal==1||oldVal==0){
return oldVal==1?"♂":"♀";
}else if(oldVal=="男"||oldVal=="Male"){
return oldVal+"♂"
}else{
return oldVal+"♀"
}
})
//1. 创建过滤器
// "en","cn"
// ↓ ↓
Vue.filter("sexFilter",function(oldVal,yuyan){
if(yuyan=="en"){
return oldVal==1?"Male":"Female"
}else{
return oldVal==1?"男":"女"
}
});
new Vue({
el:"#app",
data:{
sex:1
}
})
</script>
</body>
</html>
运行结果:
性别:♂
性别:男♂
性别:Male♂
五. axios
- 问题: 首先, 第二阶段的ajax 4步非常繁琐;其次jquery中虽然提供了$.ajax()函数,但是仅限于jquery中使用!那么到了vue中,如何一句话发送ajax请求?
- 解决: 今后只要在vue中发送ajax请求,几乎都用axios
- 什么是axios: 第三方开发的专门发送ajax请求的基于Promise的函数库。
- 如何:
(0). 下载并引入: <script src="js/axios.js">
(1). 准备: 配置axios统一的基础路径:
axios.defaults.baseURL="http://服务器端所有接口的基础地址"
(2). 发送get请求:
axios.get("服务器端接口地址的相对路径",{
params:{ //发送到服务器端的参数值列表
参数名: 参数值,
... : ...
}
}).then(result=>{//坑1: 必须用箭头函数!
//坑2: result不是直接的返回结果
result.data才是真正的返回结果
})
(3). post请求:
axios.post(
"服务器端接口地址的相对路径",
"参数1=值1&参数2=值2&..."
).then(result=>{
console.log(result.data)
})
- 示例: 使用axios发送ajax请求
6_axios.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/axios.min.js"></script>
</head>
<body>
<script>
//0. 配置统一的基础路径
axios.defaults.baseURL="http://xzserver.applinzi.com";
//1. 去东哥新浪云服务器获取学子商城首页商品列表
axios.get("/index").then(result=>{
console.log(result.data);
})
//2. 去东哥新浪云服务器获取5号商品的详细信息
axios.get("/details",{
params:{
lid:5
}
}).then(result=>{
console.log(result.data);
})
//3. 去东哥服务器验证用户名和密码,登录
axios.post(
"/users/signin",
"uname=dingding&upwd=123456"
).then(result=>{
console.log(result.data);
})
</script>
</body>
</html>
六. 生命周期:
- 问题: 在DOM或jq中,如果希望在页面加载后就自动执行一项任务(发送ajax请求),可以写在window.onload或$(function(){ … })中。但是,vue项目中写哪儿呢?
- 解决: 今后只要在vue中希望页面加载后自动执行一项任务,都要将代码写在vue对象的生命周期中。
- 什么是生命周期: new Vue()对象创建过程中所经历的所有阶段。
- 包括: 4个阶段:
(1). 创建(create)阶段:
a. 创建new Vue()对象,会创建data对象…
b. 不会创建虚拟DOM树!
(2). 挂载(mount)阶段:
a. 已经创建完new Vue()和data对象…
b. 继续创建虚拟DOM树!
=以上为必经阶段=======
(3). 更新(update)阶段:
只有在data中的变量被修改时,且这个修改会影响到界面时,才自动触发!
(4). 销毁(destroy)阶段:
只有在主动调用$destroy()函数,释放当前new Vue()对象或组件时才自动触发! - vue在每个阶段前后,都分别创建了一个钩子函数/回调函数
创建前: beforeCreate (){ ... }
(1). 创建(create)阶段
创建后: created(){
//已经创建完data对象,可以对data中的变量执行操作。
//但是暂时还没有虚拟DOM树,所以暂时不能操作页面上的元素!——如果操作,也会丢失!因为后续mount会将我们的修改尽数覆盖!
}
挂载前: beforeMount(){ ... }
(2). 挂载(mount)阶段
挂载后: mounted(){
//即有data,可以操作data中的变量
//又有虚拟DOM树,可以执行部分DOM操作
}
更新前: beforeUpdate(){ ... }
(3). 更新(update)阶段
更新后: updated(){ ... }
销毁前: beforeDestroy(){ ... }
(4). 销毁(destroy)阶段
销毁后: destroyed(){ ... }
- 示例: 当页面加载完自动发送ajax请求,加载数据到页面
7_lifecycle.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<script src="js/axios.min.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(p,i) of products">
{{p.pid}} || {{p.title}} || {{p.price}}
</li>
</ul>
</div>
<script>
//所以代码一律放在new Vue()内部!
var vm=new Vue({
el:"#app",
data:{
products:[]
},
beforeCreate(){
console.log(`创建data之前自动执行...`)
},
created(){
console.log(`创建data之后自动执行...`)
},
beforeMount(){
console.log(`挂载页面之前自动执行...`)
},
mounted(){//生命周期钩子函数
//this->new Vue()
//this.变量
console.log(`挂载页面之后自动执行...`)
axios.get("http://xzserver.applinzi.com/index")
// .then(function(result){//错误
// //普通回调函数中的this->window
// //this.products -> window.products
.then(result=>{
//内部的this->外部mounted()的this->new Vue()
this.products=result.data;
})
},
beforeUpdate(){
console.log(`更新前自动执行...`)
},
updated(){
console.log(`更新后自动执行...`)
},
beforeDestroy(){
console.log(`销毁前自动执行...`)
},
destroyed(){
console.log(`销毁后自动执行...`)
}
});
</script>
</body>
</html>
运行结果:
• 1 || Apple MacBook Air系列 || 5988
• 2 || 小米Air 金属超轻薄 || 3488
• 3 || 联想E480C 轻薄系列 || 5399
• 4 || 华硕RX310 金属超极本 || 4966
• 5 || 联想小新700 电竞版游戏本 || 6299
• 6 || 戴尔灵越燃7000 轻薄窄边 || 5199
• 7 || 华为 || 5888
总结:
- 绑定语法+13种指令
(1). 如果元素的内容需要随变量自动变化: {{}}
(2). 如果元素的属性值需要随变量自动变化: :
(3). 控制一个元素显示隐藏: v-show
(4). 控制两个元素二选一显示: v-if v-else
(5). 多个元素多选一显示: v-if v-else-if v-else
(6). 只要反复生成多个相同结构的元素组成列表时: v-for :key="唯一标识"
(7). 只要绑定事件: @ $event
(8). 防止用户短暂看到{{}}: v-cloak和v-text
(9). 只要绑定原始HTML代码片段内容: v-html
(10). 如果元素的内容只在首次加载时绑定一次,之后都不会改变: v-once
(11). 保护内容中的{{}}不被编译: v-pre
(12). 今后只要想获得表单元素的值或状态: v-model
- 绑定样式:
(1). 需要精确修改某一个css属性,就绑定style:
a. 不考虑多个元素都要修改同一种内联css属性的情况
<元素 style="固定样式" :style="{css属性:变量名, ...}"
data:{
变量名:css属性值
... : ...
}
b. 多个元素可能修改同一种内联css属性,避免css属性名冲突
<元素1 style="固定样式" :style="变量名1">
<元素2 style="固定样式" :style="变量名2">
data:{
变量名1:{
css属性名: 属性值,
... : ...
},
变量名2:{
css属性名: 属性值,
... : ...
}
}
(2). 只要批量修改一个元素的多个css属性就绑定class
a. 不考虑多个元素都要修改同一种class的情况
<元素 class="固定class" :class="{class名:变量名, ...}"
data:{
变量名:true或false,
... : ...
}
b. 多个元素可能修改同一个class,避免冲突
<元素1 class="固定class" :class="变量名1"
<元素2 class="固定class" :class="变量名2"
data:{
变量名1:{
class名:true或false,
... : ...
},
变量名2:{
class名:true或false,
... : ...
},
}
- 只要希望在页面加载时自动对元素执行一些初始化操作时就用自定义指令:
(1). 添加自定义指令:
Vue.directive("自定义指令名",{
inserted(domElem){
对domElem执行DOM操作
}
})
(2). 使用自定义指令:
<元素 v-自定义指令名>
- 今后只要根据其他变量的值动态计算出一个属性值就用计算属性:
<元素>{{计算属性}}</元素>
new Vue({
el:"#app",
data:{...},
methods:{...},
computed:{
计算属性名(){
计算过程
return 计算结果
}
}
})
- 希望将变量的原始值先加工后再显示给用户看时就用过滤器:
Vue.filter("过滤器名",function(oldVal, 自定义形参,...){
return 加工后的新值
})
<元素>{{ 变量 | 过滤器(实参值, ...) | ... }}</元素>
- 只要在vue中发送ajax请求,就用axios
axios.defaults.baseURL="服务器端接口的公共基础地址部分"
axios.get(
"服务器端接口地址的相对路径",
{
params:{ 参数名: 参数值, ... }
}
).then(result=>{
... result.data...
})
或
axios.post(
"服务器端接口地址的相对路径",
"参数名1=参数值1&参数名2=参数值2&..."
).then(result=>{
... result.data...
})
强调: 在vue内使用axios,then中必须用箭头函数,保持then内this与外部this一致,都指向当前new Vue()对象
7. vue生命周期4个阶段 8个钩子函数
beforeCreate(){ ... }
(1). 创建(create)
created(){ ... }
beforeMount(){ ... }
(2). 挂载(mount)
mounted(){ ... 经常在这里发送ajax请求 ... }
beforeUpdate(){ ... }
(3). 更新(update)
updated(){ ... }
beforeDestroy(){ ... }
(4). 销毁(destroy)
destroyed(){ ... }
- 只要希望重用一块独立的功能区域就用组件:
(1). 定义组件
Vue.component(`组件标签名`,{
template:`HTML内容片段`,
data(){ return { 变量 } },
//其余和new Vue()完全相同
})
(2). 在HTML中使用自定义组件
<组件标签名/>或双标记也行
(3). 原理: new Vue()
扫描到自定义组件标签,
a.组件的template中的HTML内容代替页面中<组件标签>位置。
b. 并为这个小区域专门创建一个缩微版的vue类型对象。
1). 调用组件的data()
函数为当前组件副本创建一个专属数据对象副本。
2). 引入组件对象中的methods等其他内容到当前组件对象副本中
9. 组件化开发:
(1). 步骤:
a. 拿到页面先划分功能区域
1). 从上到下,按功能不同划分区域
2). 按是否重用划分
b. 为每个组件创建独立的.js文件,其中包含一个组件对象及其内容
c. 将所有组件引入唯一完整的html页面中,并在<div id=”app”></div>
中添加父组件标签。
(2). 运行时:
a. new Vue()扫描<div id=”app”>
,发现父组件标签,创建并替换父组件
b. 父组件扫描自己内部的template内容,创建并替换子组件
(3). 三种组件:
a. 根组件: new Vue()
b. 全局组件: Vue.component(…)
c. 子组件: 3步
1).
var 子组件对象名={
内容必须符合组件的要求
}
子组件对象名必须是驼峰命名
2).
父组件对象中:{
... ...
components{ 子组件对象名, ... ,... }
}
子组件对象名必须是驼峰命名
3). 父组件template中用<子组件标签名/>引入子组件内容
components会将子组件对象名的驼峰命名自动翻译为-分隔
所以, 使用子组件标签时,要用-分隔多个单词
(2). 组件间传参: 父给子
a. 父组件给:
<子组件 :自定义属性名="父组件变量">
b. 子组件取:
props:["自定义属性名"]
结果: 在子组件内,props中的"自定义属性名"与子组件自己data中的变量用法完全相同!