VUE-模板语法
插值操作
简单赋值
<div id='demo'>
<h1>{{greet}}</h1>
<h2>{{firstName}} {{lastName}}</h2>
<h2>{{firstName + ' ' + lastName}}</h2>
<h3>计数:{{counter}}</h3>
<h3>计数:{{counter * 2}}</h3>
</div>
<script>
const demo = new Vue({
el: '#demo',
data: {
greet: 'hello',
firstName: 'cercis',
lastName: 'chinensis',
counter: 2
}
})
</script>
赋值指令
- mustache
{{}}基本赋值指令,将data中的文本数据,赋给html - v-once
该指令表示元素和组件只渲染一次,不会随着数据的改变而改变。 - v-html
当请求的数据是以html标签展示的,该指令可以将html标签解析出来并进行渲染
<div id='demo'>
<h4 v-html="url">{{url}}</h4>
</div>
<script>
const demo = new Vue({
el: '#demo',
data: {
url: '<a href="http://www.baidu.com">百度一下</a>'
}
})
</script>
- v-text
与{{text}}用法类型,但会覆盖其他字符。而{{}}可以拼接字符进行显示 - v-pre
显示最原始的字符,不经过编译解析。 - v-cloak
在vue解析之前,隐藏源代码,解析结束后,显示出渲染后的页面
绑定属性v-bind
作用
动态绑定属性,或者向另一个组件传递props值
语法糖-缩写
:
基本使用
<div id='demo'>
<!-- <img v-bind:src="imgUrl" alt=""> -->
<!-- 语法糖写法 -->
<img :src="imgUrl" alt="">
</div>
<script>
const demo = new Vue({
el: '#demo',
data: {
imgUrl: 'https://tse1-mm.cn.bing.net/th?id=OIP-C.QU30yid6jcEUB7NhJ9_gSAHaE8&w=254&h=170&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2'
}
})
</script>
动态绑定class
对象语法
<div id='demo'>
<!-- 直接绑定 -->
<!-- 直接绑定 -->
<h1 v-bind:class="active">{{greet}}</h1>
<!-- 语法糖写法 -->
<h2 :class="active">{{firstName}} {{lastName}}</h2>
<!-- 通过判断,传入多个值 -->
<h2 :class="{colorRed: isActive, colorGreen: isLine}">{{firstName + ' ' + lastName}}</h2>
<!-- 和普通类同时存在 -->
<h2 class="title" :class="{colorRed: isActive, colorGreen: isLine}">{{firstName + ' ' + lastName}}</h2>
<!-- 类比较复杂,可以防止methods或者computed中 -->
<h2 class="title" :class="getClasses()">{{firstName + ' ' + lastName}}</h2>
</div>
<script>
const demo = new Vue({
el: '#demo',
data: {
greet: 'hello',
firstName: 'cercis',
lastName: 'chinensis',
active: 'colorRed',
line: 'colorGreen',
isActive: true,
isLine: true
},
methods: {
getClasses: function() {
return {
colorRed: this.isActive,
colorGreen: this.isLine
}
}
}
})
</script>
数组语法
<div id='demo'>
<!-- 数组语法 -->
<!-- 和普通类同时存在,直接传值 -->
<h2 class="title" :class="['colorRed', 'colorGreen']">{{firstName + ' ' + lastName}}</h2>
<!-- 和普通类同时存在,可以传变量 -->
<h2 class="title" :class="[active, line]">{{firstName + ' ' + lastName}}</h2>
<!-- 类比较复杂,可以放在methods或者computed中 -->
<h2 class="title" :class="getClass()">{{firstName + ' ' + lastName}}</h2>
</div>
<script>
const demo = new Vue({
el: '#demo',
data: {
greet: 'hello',
firstName: 'cercis',
lastName: 'chinensis',
counter: 2,
active: 'colorRed',
line: 'colorGreen',
isActive: true,
isLine: true
},
methods: {
getClass: function() {
return [this.active, this.line]
}
}
})
</script>
案例
点击元素,该元素的样式改变,其他元素样式不变
<div id="test1">
<ul>
<li v-for="(con, index) in contents" :class="getColor(index)" @click="getColorFlag(index)">{{index}}{{con}}</li>
</ul>
</div>
<script>
const test = new Vue({
el: '#test1',
data: {
contents: ['吹拉弹唱', '说学逗唱', '琴棋书画'],
active: 'colorRed',
isActive: false,
current: -1
},
methods: {
getColor: function(obj) {
if (obj == this.current) {
return {
colorRed: this.isActive
}
}
},
getColorFlag: function(obj) {
this.isActive = true;
this.current = obj;
}
}
})
</script>
动态绑定style
对象语法
<div id="test2">
<!-- 对象语法 -->
<h1 :style="{fontSize: finalSize + 'px', backgroundColor: finalColor}">{{text}}</h1>
<h1 :style="getStyle1()">{{text}}</h1>
</div>
//动态绑定style
const test2 = new Vue({
el: '#test2',
data: {
text: 'hello world',
finalSize: 100,
finalColor: 'pink'
},
methods: {
getStyle1: function() {
return {
fontSize: this.finalSize + 'px',
backgroundColor: this.finalColor
}
}
}
})
数组语法
<div id="style1">
<!-- 数组语法 -->
<h1 :style="[baseStyle, baseStyle1]">{{text}}</h1>
</div>
<script>
//动态绑定style
const style1 = new Vue({
el: '#style1',
data: {
text: 'hello world',
finalSize: 100,
finalColor: 'pink',
baseStyle: {
fontSize: 100 + 'px',
backgroundColor: 'green'
},
baseStyle1: {
color: 'white'
}
}
})
</script>
计算属性
基本使用
<div id='compute1'>
<h2>{{greet}} {{fullName}}</h2>
<!-- 等价于 <h2>{{greet}} {{getfullName()}}</h2> -->
</div>
<script>
//计算属性
const compute1 = new Vue({
el: '#compute1',
data: {
greet: 'hello',
firstName: 'cercis',
lastName: 'chinensis'
},
computed: {
fullName: function() {
return this.firstName + ' ' + this.lastName
}
},
methods: {
getfullName: function() {
return this.firstName + ' ' + this.lastName
}
}
});
</script>
复杂操作
<div id='compute1'>
<h3>总价:{{totalPrice}}</h3>
</div>
<script>
//计算属性
const compute1 = new Vue({
el: '#compute1',
data: {
books: [{
id: 0,
name: '桃花扇',
price: 562
}, {
id: 1,
name: '西厢记',
price: 227
}, {
id: 2,
name: '735',
price: 235
}, {
id: 3,
name: '长生殿',
price: 223
}]
},
computed: {
totalPrice: function() {
let result = 0
for (let i = 0; i < this.books.length; i++) {
result += this.books[i].price
}
return result
}
}
});
setter和getter
<div id='compute1'>
<h2>{{greet}} {{fullName}}</h2>
<!-- 等价于 -->
<h2>{{greet}} {{getfullName()}}</h2>
<h2>{{greet}} {{full}}</h2>
</div>
<script>
//计算属性
const compute1 = new Vue({
el: '#compute1',
data: {
greet: 'hello',
firstName: 'cercis',
lastName: 'chinensis'
},
computed: {
//方法一
fullName: function() {
return this.firstName + ' ' + this.lastName;
},
//方法二
full: {
set: function() {
//计算属性通常不使用set方法,是只读属性
},
get: function() {
//常用get方法,用法类似于“fullName”,因此常用方法一
return this.firstName + ' ' + this.lastName
}
}
}
});
</script>
computed和methods
- computed和methods都可以实现对值进行操作
- 计算属性computed会对计算结果进行缓存,当操作参数没有发生变化时,计算属性只会调用一次,比methods效率更高。
ES6语法
let/var
var
没有块级作用域,会引发的问题
- if:在if里定义var变量,在if外该变量被修改后,最后读取的是被修改过的
- for:在for里定义var变量,该变量在循环中被遍历修改后,若想取到最初的值,只能采用闭包
闭包: 因为函数一个作用域。因此能将变量的作用域固定在函数中
let(es6)
为了解决var没有块级作用域的问题,应运而生
const
修饰为常量,不可以再次赋值,保证数据的安全性
注:
- const修饰的标识符被赋值后,不能修改
- 使用const定义标识符,必须进行赋值
- 常量的含义是指向的对象不能修改,但可以修改对象内部的属性。
对象字面量
- 属性字面量
<!-- ES6语法 -->
<script>
const name = 'name';
const age = 20;
const gender = 'female';
// ES5
const xxy = new Object({
name: name,
age: age,
gender: gender
})
//ES6
const xx = {
name,
age,
gender
}
console.log(xxy);
console.log(xx);
</script>
2.函数字面量
// ES5
const xxy = new Object({
greet: function() {
console.log('say hi');
}
})
//ES6
const xx = {
greet() {
console.log('say hi');
}
}
事件监听v-on
作用
绑定事件监听器
语法糖-缩写
@
基本使用
<div id="listen1">
<h1>{{counter}}</h1>
<!-- 基础写法 -->
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
<!--语法糖写法 -->
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
<!-- v-on-->
<script>
const listen1 = new Vue({
el: '#listen1',
data: {
counter: 0
},
methods: {
add() {
this.counter++
},
sub() {
this.counter--
}
}
});
</script>
参数传递
<!-- v-on 无参数传递 -->
<button @click="parameter()">无参数</button>
<button @click="parameter">无参数</button>
<!-- v-on 参数传递 -->
<button @click="parameter1('参数')">单传参数</button>
<button @click="parameter2('参数', $event)">参数和event</button>
<script>
const listen1 = new Vue({
el: '#listen1',
data: {
counter: 0
},
methods: {
parameter() {
console.log('no pram');
console.log(event);
},
parameter1(a, b) {
console.log(a);
console.log(event);
},
parameter2(a) {
console.log(a);
console.log(event);
}
}
});
</script>
修饰符
<!-- .stop修饰符 -->
<div @click="divClick">
<button @click="btnClick">冒泡</button>
<button @click.stop="btnClick">阻止冒泡</button>
</div>
<!-- .prevent修饰符 -->
<form action="http://www.baidu.com">
<input type="submit" value="提交" @click="submitClick">
<input type="submit" value="阻止默认提交" @click.prevent="submitClick">
</form>
<!-- .{key, enter}修饰符 -->
<input type="text" placeholder="监听键盘按下后的操作" id="" @keyup="keyUp">
<input type="text" placeholder="键盘按下,监听回车后的操作" id="" @keyup.enter="keyUp">
<!-- .once修饰符 -->
<button @click="btnClick">点击多次</button>
<button @click.once="btnClick">只触发一次</button>
条件判断
<!-- v-if v-else-if v-else -->
<div id="if1">
<!-- 单条件判断1 -->
<div v-if="isShow">
<h1>show1</h1>
<h1>show2</h1>
</div>
<!-- 单条件判断2 -->
<div v-if="isShow">
<h1>show1</h1>
<h1>show2</h1>
</div>
<div v-else>
<h1>isShow is false</h1>
</div>
<!-- 多条件判断 -->
<h1 v-if="age>=40">中年</h1>
<h1 v-else-if="age>=18">青年</h1>
<h1 v-else-if="age>=10">少年</h1>
<h1 v-else>儿童</h1>
</div>
<!-- v-if v-else-if v-else -->
<script>
const if1 = new Vue({
el: '#if1',
data: {
isShow: true,
age: 5
}
})
</script>
案例
<div id="if2">
<!-- 切换登录 -->
<span v-if="isChange">
<label for="">用户名</label>
<input type="text" id="userName" placeholder="用户名">
</span>
<span v-else>
<label for="">邮箱</label>
<input type="text" id="email" placeholder="邮箱">
</span>
<button @click="changeLoginType">1.切换登录方式</button>
<button @click="!isChange">2.切换登录方式</button>
</div>
<!-- v-if v-else-if v-else -->
<script>
const if2 = new Vue({
el: '#if2',
data: {
isChange: true
},
methods: {
changeLoginType() {
this.isChange = this.isChange == true ? false : true;
}
}
})
</script>
思考:切换登录时,input里输入的内容,在切换的时候不会清空。
原因:vue在进行DOM渲染时,不会渲染出所有的元素,考虑性能,会复用已经存在的元素。
解决:key,可以对元素进行标识,不会出现复用的情况。
<div id="if2">
<!-- 切换登录 -->
<span v-if="isChange">
<label for="">用户名</label>
<input type="text" id="userName" placeholder="用户名" key="userName">
</span>
<span v-else>
<label for="">邮箱</label>
<input type="text" id="email" placeholder="邮箱" key="email">
</span>
<button @click="changeLoginType">切换登录方式</button>
</div>
v-if v-show
<div id="show">
<!-- 切换登录 -->
<span v-show="isChange">
<label for="">用户名</label>
<input type="text" id="userName" placeholder="用户名" key="userName">
</span>
<span v-show="!isChange">
<label for="">邮箱</label>
<input type="text" id="email" placeholder="邮箱" key="email">
</span>
<button @click="changeLoginType">切换登录方式</button>
</div>
<!-- v-show -->
<script>
const show = new Vue({
el: '#show',
data: {
isChange: true
},
methods: {
changeLoginType() {
this.isChange = !this.isChange
}
}
})
</script>
- 在判断是否渲染出一个元素时,v-if是将元素在DOM里直接去掉。v-show是将元素的样式设为display
- v-if 一般应用于对大段元素进行判断。应用场景在对服务器传过来的数据进行渲染时,就会判断,以哪种样式进行呈现
- v-show 当需要对元素的显示和隐藏进行来回切换,比较频繁的时候,使用v-show会更好。
循环遍历
<div id="for1">
<!-- 遍历数组 -->
<ul>
<!-- 获取值 -->
<li v-for="item in books">{{item}}</li>
<!-- 获取索引-值 -->
<li v-for="(item, index) in books">{{index}}-{{item}}</li>
</ul>
<!-- 遍历对象 -->
<ul>
<!-- 获取值 -->
<li v-for="item in bookContent">{{item}}</li>
<!-- 获取键值对 -->
<li v-for="(item, key) in bookContent">{{key}}:{{item}}</li>
<!-- 获取键值对和索引,索引是默认赋的,没有什么价值,对象是无序的 -->
<li v-for="(item, key, index) in bookContent">{{index}}-{{key}}:{{item}}</li>
</ul>
</div>
<!-- v-for -->
<script>
const for1 = new Vue({
el: '#for1',
data: {
books: ['桃花扇', '牡丹亭', '西厢记', '长生殿'],
bookContent: {
author: '吴承恩',
name: '《西游记》',
type: '长篇神魔小说'
}
}
})
</script>
注:
- 组件的key属性,使用v-for时,给对应元素或组件加上:key属性。当key给每个节点做了唯一标识,当对元素或组件进行修改操作时,diff算法能正确地识别节点,并找到正确的位置进行修改。
- key主要是为了更高效地更新虚拟DOM
- 设置key值时,必须保证它能唯一标识此元素
响应式数组操作
对数组进行操作,有的可以直接渲染出来,有的只是改变了值,但不会渲染到页面
<div id="for1">
<!-- 响应式数组 -->
<ul>
<li v-for="item in women">{{item}}</li>
</ul>
<button @click="insert1">新增push</button>
<button @click="insert2">新增unshift</button>
<button @click="insert3">新增splice</button>
<button @click="delete1">删除pop</button>
<button @click="delete2">删除shift</button>
<button @click="delete3">删除splice</button>
<button @click="update">替换</button>
<button @click="sort">排序</button>
<button @click="reverse">翻转</button>
<button @click="noShow">不会响应</button>
</div>
<!-- v-for -->
<script>
const for1 = new Vue({
el: '#for1',
data: {
women: ['阿朱', '王语嫣', '木婉清', '钟灵']
},
methods: {
insert1() {
// 尾结点新增,可新增多个参数
this.women.push('周芷若', '赵敏')
},
insert2() {
// 头结点新增,可新增多个参数
this.women.unshift('赵灵儿', '林月如')
},
insert3() {
//任意位置插入,,可插入多个参数
this.women.splice(2, 0, '穆念慈', '黄蓉')
},
delete1() {
//删除最后一个元素
this.women.pop()
},
delete2() {
//删除第一个元素
this.women.shift()
},
delete3() {
//删除任意位置、任意个数的元素
this.women.splice(2, 2)
},
update() {
//进行元素替换
this.women.splice(2, 2, '小龙女', '公孙绿萼')
},
sort() {
this.women.sort()
},
reverse() {
this.women.reverse()
},
noShow() {
this.women[0] = '阿紫';
console.log(this.women);
}
},
});
</script>
注:在对数组的值,通过索引号进行赋值的时候,是不响应的,不会渲染到页面。但若数组的值是对象,对对象的属性进行赋值操作,是会渲染到页面的
案例-购物车
const shopCar = new Vue({
el: '#shopCar',
data: {
books: [{
id: '1',
name: '《算法导论》',
date: '2006-9',
number: 1,
price: 85
}, {
id: '2',
name: '《UNIX编程艺术》',
date: '2006-2',
number: 1,
price: 59
}, {
id: '3',
name: '《编程珠玑》',
date: '2008-10',
number: 1,
price: 39
}, {
id: '4',
name: '《代码大全》',
date: '2006-3',
number: 1,
price: 128
}],
notEmpty: true
},
computed: {
totalPrice() {
//方法一:for循环
// let sum = 0;
// for (let i = 0; i < this.books.length; i++) {
// sum += this.books[i].number * this.books[i].price;
// }
// return sum;
//方法二:高阶函数
return this.books.reduce(function(preValue, book) {
return preValue + book.number * book.price
}, 0)
},
methods: {
add(index) {
//一开始对数组是响应式理解有欠缺,因此通过splice操作来进行替换操作,改变number的值
// this.books.splice(index, 1, {
// id: this.books[index].id,
// name: this.books[index].name,
// date: this.books[index].date,
// number: this.books[index].number + 1,
// price: this.books[index].price
// })
//数组里的值,是对象时,可对对象的属性直接操作
this.books[index].number++;
},
sub(index) {
this.books[index].number--;
},
clear(index) {
if (this.books.length >= 0) {
this.books.splice(index, 1);
if (this.books.length == 0) {
this.notEmpty = false;
}
}
}
},
filters: {
showPrice(price) {
return '¥' + price.toFixed(2)
}
}
})
高阶函数
filters
过滤函数,对数组的值进行过滤操作,返回结果为true,就将元素保留,否则略过
map
映射函数,对数组进行操作后返回,与原数组的值一一对应
reduce
归并函数,对数组进行累计操作,可完成对数组的值进行求和
v-model
v-model基本使用
<div id="model">
<!-- v-model是v-bind和v-on实现双向绑定的语法糖 -->
<input type="text" name="" id="" v-model="message">
<input type="text" name="" id="" :value="message" @input="message=$event.target.value">
</div>
v-model结合勾选框使用
- radio
- checkbox
- select
<!-- 单选框, radio -->
<label for="">
<input type="radio" name="" id="" value="男" v-model="gender">男
</label>
<label for="">
<input type="radio" name="" id="" value="女" v-model="gender">女
</label>
<label for="">
<input type="radio" name="gender" id="" value="男">男
</label>
<label for="">
<input type="radio" name="gender" id="" value="女">女
</label>
<h2>所选性别:{{gender}}</h2>
<!-- 多选框,checkbox -->
<label for=""><input type="checkbox" name="" id="" value="辣子鸡" v-model="menu">辣子鸡</label>
<label for=""><input type="checkbox" name="" id="" value="羊肉粉" v-model="menu">羊肉粉</label>
<label for=""><input type="checkbox" name="" id="" value="糖醋排骨" v-model="menu">糖醋排骨</label>
<label for=""><input type="checkbox" name="" id="" value="剁椒鱼" v-model="menu">剁椒鱼</label>
<label for=""><input type="checkbox" name="" id="" value="麻辣香锅" v-model="menu">麻辣香锅</label>
<label for=""><input type="checkbox" name="" id="" value="莲藕排骨汤" v-model="menu">莲藕排骨汤</label>
<label for=""><input type="checkbox" name="" id="" value="炸鸡" v-model="menu">炸鸡</label>
<h2>所选菜品:{{menu}}</h2>
值绑定
可将以上例子的参数,进行动态绑定
<!-- 值绑定 -->
<!-- 多选框 -->
<label for="" v-for="item in originMenu">
<input type="checkbox" name="" id="" :value="item" v-model="menu">{{item}}
</label>
<!-- select单选 -->
<select name="" id="" v-model="menu">
<option v-for="item in originMenu" :value="item">{{item}}</option>
</select>
<!-- select多选 -->
<select name="" id="" v-model="menu" multiple>
<option v-for="item in originMenu" :value="item">{{item}}</option>
</select>
修饰符
- lazy
- number
- trim
<!-- 修饰符 -->
<!-- lazy:懒加载,不会实时绑定参数,而是当失去焦点或者回车的时候,再绑定值 -->
<label for=""><input type="text" name="" id="" v-model.lazy="number">{{number}}</label>
<!-- number:将输入的参数修饰为数字类型,因为输入框中的内容会被处理为字符串类型 -->
<label for=""><input type="text" name="" id="" v-model.lazy.number="number">{{typeof number}}</label>
<!-- trim:将输入的参数左右两边的空格去除 -->
<label for=""><input type="text" name="" id="" v-model.trim="number">{{number}}</label>