本文主要记录Vue2.0的干知识点 + 案例代码
Vue官网教程: https://cn.vuejs.org/v2/guide/
这两个部分操作的都是 data(){} 中的数据。
插值语法: 把指定的值放到指定的位置。
{{ js表达式 }} 读取data中的数据,可对读取到的数据进行处理。
v-bind:属性名="xxx" 单向绑定,数据只能从 data 流向页面,简写为 : 。
v-model:value="xxx" 双向绑定,数据不仅能从 data 流向页面,还能从页面流向 data,简写为 v-model="xxx" 。
v-text = "固定值"类似于innerText属性,作用与{{}}类似,但只能写一个固定的值。
v-html="固定值" 类似于innerHTML属性,作用与{{}}类似,但只能写一个固定的值。
v-once 具有v-once的标签中的数据只在界面上渲染一次。
v-pre 标签具有v-pre,界面会原封不动地展示标签内的内容。
v-cloak 标签具有v-cloak,在界面和数据还没完全渲染的时候,它不会展示,当界面和数据渲染完成,它才显示。需要和css的代码 [v-cloak]{ display: none } 一起配合使用。
字符串写法:
<div :class="{ active: isActive , 'text-danger': hasError}">div>
data: {
isActive: true,
hasError: false
}
数组写法:
<div :class="[activeClass, errorClass]">div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
对象写法:
<div :class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
<!-- 绑定style样式--对象写法 -->
<div class="basic" :style="styleObj"></div>
<!-- 绑定style样式--数组写法 -->
<div class="basic" :style="styleArr"></div>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
styleObj:{
fontSize: '40px',
color:'red',
},
styleArr:[
{
fontSize: '40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
这部分操作的都是是 methods:{} 中的方法。
注意: 普通函数中的this指代的是Vue实例,箭头函数中的this指代的是就不是Vue实例,箭头函数绑定到父上下文。
| 鼠标 | 说明 | 键盘 | 说明 | 表单 | 说明 |
|---|---|---|---|---|---|
click | 鼠标单击 | keydown | 键盘按下 | blur | 失去焦点 |
dblclick | 鼠标双击 | keyup | 键盘抬起 | focus | 获得焦点 |
mousemove | 鼠标移动 | keypress | 按下按键 | change | 内容变化 |
mouseover | 鼠标悬浮 | ||||
mouseout | 鼠标离开 |
vue中常用的按键别名:
键盘事件注意事项:
v-on:click="方法名" 绑定一个点击触发的方法,简写为 @click 。
触发一个事件会经历以下两个过程:
默认情况,我们只是监测冒泡过程,只有给事件的触发条件加上了事件修饰符才会监测捕获过程。
事件修饰符:使用格式:@click.修饰符1.修饰符2="方法名"
| 修饰符 | 说明 |
|---|---|
prevent | 阻止默认事件 |
stop | 阻止事件冒泡 |
once | 事件只触发一次 |
capture | 使用事件的捕获模式 |
self | 只有目标DOM是当前操作时才触发事件 |
passive | 事件的默认行为立即执行 |
计算属性:根据已经存在的属性,去加工获得新的属性或属性值。对于复杂的逻辑,应该使用计算属性。
Objcet.defineproperty()方法提供的getter和setter<div id="app">
<p>Original message: "{{ message }}"p>
<p>Computed reversed message: "{{ reversedMessage }}"p>
div>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello'
},
computed: {
// a computed getter
// 这里可以把function省略
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
计算出的属性是基于它们的依赖关系进行缓存的。计算属性只会在其某些依赖项发生更改时才会重新评估。这意味着只要message没有改变,多次访问reversedMessage计算属性将立即返回先前计算的结果,而不必再次运行该函数。这就比methods效率更高。
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{fullName}}span>
div>
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{
fullName:{
get(){
return this.firstName + '-' + this.lastName
},
set(value){
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
监视属性:监视数据,当数据发生变化的时候,就会自动回调函数,进行相关的操作。
监视属性简写:如果监视属性除了handler没有其他配置项的话,可以进行简写。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
//正常写法
isHot:{
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
//简写
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
}
}
})
//正常写法
vm.$watch('isHot',{
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
//简写
vm.$watch('isHot',function(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
})
<div id="demo">{{ fullName }}div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
深度监视:监视对象的属性值的变化。
deep:true 可以监测对象内部值的改变(多层) <div id="root">
<h3>a的值是:{{numbers.a}}h3>
<button @click="numbers.a++">点我让a+1button>
<h3>b的值是:{{numbers.b}}h3>
<button @click="numbers.b++">点我让b+1button>
div>
new Vue({
el:'#root',
data:{
isHot:true,
numbers:{
a:1,
b:1,
}
},
watch:{
//监视多级结构中所有属性的变化
numbers:{
deep:true,
handler(){
console.log('numbers改变了')
}
}
//监视多级结构中某个属性的变化
/* 'numbers.a':{
handler(){
console.log('a被改变了')
}
} */
}
})
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>条件渲染title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>当前的n值是:{{n}}h2>
<button @click="n++">点我n+1button>
<h2 v-show="true">Hello,{{name}}!h2>
<div v-if="n === 1">Angulardiv>
<div v-else-if="n === 2">Reactdiv>
<div v-else>Vuediv>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'jojo',
n:0
}
})
script>
html>
v-if 当表达式为真时,才会显示组件内容,否则组件不可见。
写法:
v-if="表达式"v-else-if="表达式"v-else适用场景:切换频率较低的场景(开发阶段需要经常刷新页面,建议使用v-show)。
注意:v-if 可以和 v-else-if 、 v-else 一起使用,但要求结构不能被打断
v-show 作用同 v-if 类似,表达式为真才显示组件内容,否则组件不可变。
适用于:切换频率较高的场景。
注意: 在这种情况下,它会多次重复该模板。 react、vue中的key有什么作用?(key的内部原理) 用index作为key可能会引发的问题: 开发中如何选择key? 要显示一个数组的过滤或排序版本,而不需要实际改变或重置原始数据。在这种情况下,可以创建一个返回过滤或排序数组的计算属性。 筛选元素: 列表排序: 变化方法: Vue包装观察数组的变异方法,以便它们也会触发视图更新。包装的方法是: 监视原理: 特别注意: Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data等) 添加属性。 收集表单数据: 过滤器是vue中的一个特性,作用是对文本进行格式化的作用。 注意:vue 1.0中有内置的过滤器,在2.0中去掉了内置过滤器,只有自定义过滤器。 过滤器只能应用在两个地方: 过滤器的语法: 注意: Vue生命周期:v-show 不能与一起用,不然会无法显示,v-show 建议和 5.列表渲染v-for
1.遍历数组元素
v-for 用数组将元素映射到元素。<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
li>
ul>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
li>
ul>
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
],
2.遍历对象属性
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
li>
ul>
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
<ul>
<li v-for="(value,k) in car" :key="k">
{{k}}-{{value}}
li>
ul>
car:{
name:'奥迪A8',
price:'70万',
color:'黑色'
},
3.遍历字符串
<ul>
<li v-for="(char,index) in str" :key="index">
{{char}}-{{index}}
li>
ul>
str:'hello'
4.遍历指定次数
<ul>
<li v-for="(number,index) in 5" :key="index">
{{index}}-{{number}}
li>
ul>
<div>
<span v-for="n in 10">{{ n }} span>
div>
5.小结
v-for,其中key可以是index,也可以是遍历对象的唯一标识key的原理:
当Vue更新呈现的元素列表时v-for,默认情况下它使用“就地补丁”策略。如果数据项的顺序发生了变化,Vue将不会移动DOM元素来匹配项目的顺序,而是会将每个元素就地修补并确保它反映应该在该特定索引处呈现的内容。
这个默认模式是有效的,但只适用于你的列表渲染输出不依赖子组件状态或临时DOM状态(例如表单输入值)的情况。
为了给Vue一个提示,以便它可以跟踪每个节点的身份,并因此重新使用和重新排序现有元素,您需要key为每个项目提供一个唯一的属性。一个理想的价值key将是每个项目的唯一ID。
它的作用类似于一个属性,所以你需要使用v-bind它来将它绑定到动态值。<div v-for="item in items" :key="item.id">
<!-- content -->
</div>
<ul>
<li v-for="(item, i) in list" :key="item.id">
<input type="checkbox"> {{item.name}}
li>
ul>
list: [
{ id: 1, name: '李斯' },
{ id: 2, name: '吕不韦' },
{ id: 3, name: '嬴政' }
]
虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
若虚拟DOM中内容没变, 直接使用之前的真实DOM
若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM6.列表过滤
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) of filPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
li>
ul>
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'}
]
...
computed:{
filPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
<li v-for="n in evenNumbers">{{ n }}li>
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
<input type="text" placeholder="请输入名字" v-model="keyWord">
<button @click="sortType = 2">年龄升序button>
<button @click="sortType = 1">年龄降序button>
<button @click="sortType = 0">原顺序button>
<ul>
<li v-for="(p,index) of filPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
li>
ul>
data:{
persons:[
{id:'001',name:'马冬梅',age:30,sex:'女'},
{id:'002',name:'周冬雨',age:45,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'}
],
keyWord:'',
sortType:0,//0代表原顺序,1代表升序,3代表降序
},
computed:{
filPersons(){
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
if(this.sortType){
arr.sort((p1, p2)=>{
return this.sortType ===1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
7.数据监视
push()pop()shift()unshift()splice()sort()reverse() <div id="root">
<h1>学生信息</h1>
<button @click="student.age++">年龄+1岁</button><br/>
<button @click="addSex">添加性别属性,默认值:男</button> <br/>
<button @click="addFriend">在列表首位添加一个朋友</button> <br/>
<button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
<button @click="addHobby">添加一个爱好</button> <br/>
<button @click="updateHobby">修改第一个爱好为:开车</button><br/>
<button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br/>
<h3>姓名:{{student.name}}</h3>
<h3>年龄:{{student.age}}</h3>
<h3 v-if="student.sex">性别:{{student.sex}}</h3>
<h3>爱好:</h3>
<ul>
<li v-for="(h,index) in student.hobby" :key="index">
{{h}}
</li>
</ul>
<h3>朋友们:</h3>
<ul>
<li v-for="(f,index) in student.friends" :key="index">
{{f.name}}--{{f.age}}
</li>
</ul>
</div>
const vm = new Vue({
el:'#root',
data:{
student:{
name:'tom',
age:18,
hobby:['抽烟','喝酒','烫头'],
friends:[
{name:'jerry',age:35},
{name:'tony',age:36}
]
}
},
methods: {
addSex(){
//Vue.set(this.student,'sex','男')
this.$set(this.student,'sex','男')
},
addFriend(){
this.student.friends.unshift({name:'jack',age:70})
},
updateFirstFriendName(){
this.student.friends[0].name = '张三'
},
addHobby(){
this.student.hobby.push('学习')
},
updateHobby(){
this.student.hobby.splice(0,1,'开车')
},
removeSmoke(){
this.student.hobby = this.student.hobby.filter((h)=>{
return h !== '抽烟'
})
}
}
})
Vue.set(target,propertyName/index,value)
vm.$set(target,propertyName/index,value)push()、pop()、shift()、unshift()、splice()、sort()、reverse()Vue.set() 或 vm.$set()6.收集表单数据
1.案例
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>收集表单数据title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.js">script>
head>
<body>
<div id="root">
<form @submit.prevent="demo">
账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
密码:<input type="password" v-model="userInfo.password"> <br/><br/>
年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
性别:
男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
<br/><br/>
所属校区:
<select v-model="userInfo.city">
<option value="">请选择校区option>
<option value="beijing">北京option>
<option value="shanghai">上海option>
<option value="shenzhen">深圳option>
<option value="wuhan">武汉option>
select>
<br/><br/>
其他信息:
<textarea v-model.lazy="userInfo.other">textarea> <br/><br/>
<input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》a>
<button>提交button>
form>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
userInfo:{
account:'',
password:'',
age:0,
sex:'female',
hobby:[],
city:'beijing',
other:'',
agree:''
}
},
methods: {
demo(){
console.log(JSON.stringify(this.userInfo))
}
}
})
script>
html>
2.小结
,则v-model收集的是value值,用户输入的内容就是value值,则v-model收集的是value值,且要给标签配置value属性v-model的三个修饰符:lazy:失去焦点后再收集数据number:输入字符串转为有效的数字trim:输入首尾空格过滤7.过滤器
1.过滤器的使用
{{ xxx | xxx }}、:xx = " xxx | xxx "1.全局过滤器
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>过滤器title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.js" >script>
<script>
window.onload=function(){
// 定义全局过滤器
Vue.filter("addZero",function(value){
// 如果value的值小于10则在前面添加0然后返回,否则直接返回value值
return value<10?"0"+value:value;
});
// 构建vue实例
new Vue({
el:"#my",
data:{
},
// 方法
methods:{
}
})
}
script>
head>
<body>
<div id="my">
{值 | 过滤器的名称}}-->
<div>{{3 | addZero}}div>
<div>{{15 | addZero}}div>
<div v-bind:id="1 | addZero">11div>
<div v-bind:id="12 | addZero">15div>
div>
body>
html>
2.本地过滤器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>过滤器</title>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.js" ></script>
<script>
window.onload=function(){
// 定义全局过滤器
Vue.filter("addZero",function(value){
// 如果value的值小于10则在前面添加0然后返回,否则直接返回value值
return value<10?"0"+value:value;
});
// 构建vue实例
new Vue({
el:"#my",
data:{
},
// 方法
methods:{
},
// 定义本地过滤器
filters:{
roundNum:function(value){
// 四舍五入 小数点后保留两位
return value.toFixed(2);
},
roundNumWithPara:function(value,digit){
// 根据digit返回相应位数的小数
return value.toFixed(value,digit);
}
}
})
}
</script>
</head>
<body>
<div id="my">
<!--在双花括号中使用全局过滤器 格式:{{值 | 过滤器的名称}}-->
<div>{{3 | addZero}}</div>
<div>{{15 | addZero}}</div>
<!--在v-bind中使用全局过滤器 格式:v-bind:id="值 | 过滤器的名称"-->
<div v-bind:id="1 | addZero">11</div>
<div v-bind:id="12 | addZero">15</div>
<!--使用本地过滤器-->
<div>原始值:3.1415926,过滤后的值:{{3.1415926 | roundNum}}</div>
<!--保留小数点后3位-->
<div>原始值:3.1415926,过滤后的值:{{3.1415926 | roundNumWithPara(3)}}</div>
</div>
</body>
</html>
2.案例
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>过滤器title>
<script type="text/javascript" src="js/vue.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.js">script>
head>
<body>
<div id="root">
<h2>时间h2>
<h3>当前时间戳:{{time}}h3>
<h3>转换后时间:{{time | timeFormater()}}h3>
<h3>转换后时间:{{time | timeFormater('YYYY-MM-DD HH:mm:ss')}}h3>
<h3>截取年月日:{{time | timeFormater() | mySlice}}h3>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,11)
})
new Vue({
el:'#root',
data:{
time:Date.parse(new Date()),
},
//局部过滤器
filters:{
timeFormater(value, str="YYYY年MM月DD日 HH:mm:ss"){
return dayjs(value).format(str)
}
}
})
script>
html>
3.小结
Vue.filter(name,callback) 或 new Vue{filters:{}}{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"{{ message | filterA | filterB }}8.Vue生命周期
1.什么是vue的生命周期

2.生命周期函数
函数 说明 beforeCreate在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问 methods, data, computed等上的方法和数据。created这一步,实例已经完成的配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化。
挂载还未开始,$el属性目前不可见。
可进行的操作:调用methods中的方法,改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上,获取computed中的计算属性等。
通常在这里对实例进行预处理。beforeMount挂载开始之前被调用,相关的render函数首次被调用(虚拟DOM)
实例已经完成的配置:编译模板,把data里面的数据和模板生成html,完成了el和data 初始化。
此时还没有挂载html到页面上。mounted挂载完成(将模板中的html渲染到页面上)。
mounted只会执行一次。
一般在这阶段做一些Ajax操作。beforeUpdate实例数据更新前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程。 updated实例数据更新后调用(数据更改导致虚拟DOM重新渲染和打补丁),组件DOM已经更新,可以执行依赖于DOM的操作。
然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用。beforeDestroy实例销毁之前调用,实例仍然完全可用。
这一步还可以用this来获取实例,一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件。destroyed实例销毁之后调用,调用后,所有的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用。