Vue学习笔记
1、第一个程序:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id='root'>
<h2>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script type="text/javascript">
<!-- 关闭开发者模式提示 -->
Vue.config.productionTip=false;
<!-- 创建Vue对象实例 -->
const x = new Vue({
el: "#root",
data: {
message: "hello,Vue!"
}
})
</script>
</body>
</html>
<script src="../js/vue.js"></script> :引入vue.js库文件
- 插值语法:{{expression}},即在两个大括号中写JavaScript表达式
- 主要表达式分类如下:
- 变量表达式,例:a
- 运算表达式,例:a+b
- 函数调用表达式,例:func(1)
- 三元表达式:a === b ? a : b
2、声明式编程:
第一个程序中,有下面代码段,该方式被称为声明式编程,通过new一个Vue对象实例,来管理指定的标签,该Vue实例就是管理的id属性为root的标签
<div id='root'>
<h2>{{message}}</h2>
</div>
<script type="text/javascript">
<!-- 创建Vue对象实例 -->
const x = new Vue({
el: "#root",
data: {
message: "hello,Vue!"
}
})
</script>
3、Vue中的指令:
插值指令:{{}}
单向数据绑定:v-bind(可以简写为" : ")
双向数据绑定:v-model
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<p>插值指令:{{name}}</p>
单向数据绑定:<input type="text" v-bind:value="name"><br>
双向数据绑定:<input type="text" v-model:value="name">
单向数据绑定:<input type="text" :value="name"><br>
双向数据绑定:<input type="text" v-model="name">
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
name: 'qymlxin'
}
})
</script>
</body>
</html>
3.1、v-bind和v-model的区别
3.2、使用v-model的注意事项
v-model只能只能应用于表单类的标签上(一般绑定value属性),用在其他的标签会报错,例如下面这样写:

报错如下:

4、Vue()对象中的属性
从如下图可以看到,Vue对象实例中有很多的属性,其中以$符号开头的属性都是提供给我们开发人员使用的

4.1、Vue对象中的el的两种写法
<script>
Vue.config.productionTip = false;
const v = new Vue({
<!-- 第一种 -->
el: '#root',
data: {
name: 'qymlxin'
}
})
<!-- 第二种 -->
v.$mount('#root');
console.log(v);
</script>
- 第一种:在创建Vue对象的时候,指定el的值,上面代码也可以指定为".root",那么此对象管理的就是class属性为"root"的标签
- 第二种:在创建了Vue对象实例之后,调用其$mount()函数指定其托管的标签选择器,可以为id选择器,也可以为类选择器
4.2、Vue中的data的两种写法
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: function() {
return {
name: 'qymlxin'
}
}
})
</script>
- 第一种写法:对象式写法,在data后面直接跟一个冒号和对象,对象中写属性和值
- 第二种写法:函数式写法,在data后面跟一个函数,该函数返回一个对象,在该返回对象中写属性和值
5、MVVM模型
- M:模型(Model),对应data中的数据
- V:视图(View),模板
- VM:视图模型(ViewModel),Vue实例对象

6、数据代理
-
Object.defineProperty() 函数可以给对象添加属性,并定制化属性的参数 <script>
let person = {
name: '张三',
sex: '男'
}
Object.defineProperty(person,'age',{
get: function() {
return 'hello';
},
set(value) {
console.log(value);
}
});
console.log(Object.keys(person));
console.log(person);
</script>
- value:定义属性的值
- enumerable:控制属性是否能够被枚举,默认为false
- writable:控制属性是否能够被修改,默认为false
- configurable:控制属性是否可以被删除,默认为false
- get():在读取所定义属性时,就会自动调用,并返回一个值,该值就是该属性的值
- set():在修改所定义属性时,就会自动调用,并会收到修改的值
-
数据代理
通过getter和setter给obj2设置一个x属性,同时达到了代理obj1中的x属性的目的
let obj1 = {x:100};
let obj2 = {y:200};
Object.defineProperty(obj2,'x',{
get() {
return obj1.x;
},
set(value) {
obj1.x = value;
}
})

Vue中的data对象的属性被存储在了_data对象中,而我们的Vue实例中的跟data中一样的属性是通过数据代理代理的_data中的属性值,同时通过getter和setter获取和修改其值
7、事件处理
7.1、点击事件v-on:click
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<h2>你好,我是{{name}}</h2>
<button v-on:click="showInfo($event,66)">点击我1</button>
<button @click="showInfo($event,66)">点击我2</button>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
name: 'qymlxin'
},
methods: {
showInfo(event,number){
console.log(event);
console.log(number);
alert('你好!');
}
}
})
</script>
</body>
</html>
v-on:的简写方式为一个@符号
$event关键字,可以在绑定事件时,将event事件参数传给函数调用
7.2、事件修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<a href="http://www.baidu.com" @click.="showInfo">点击我</a>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
},
methods: {
showInfo() {
alert('你好!');
}
}
})
</script>
</body>
</html>
- prevent: 阻止默认事件(常用);
- stop: 阻止事件冒泡(常用);
- 事件只触发一次(常用);
- capture: 使用事件的捕获模式;
- 只有event.target是当前触发的元素才触发事件;
- passive: 事件的默认行为立即执行,无需等待事件回调函数执行完毕;
8、计算属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
computed: {
fullName: {
get() {
console.log('执行了getter');
return this.firstName+this.lastName;
},
set(value) {
var arr = value.split('-');
this.firstName = arr[0];
this.lastName = arr[1];
}
}
}
})
</script>
</body>
</html>
计算属性是写在computed后面的对象中的,对象中的属性也要写成一个对象,并且必须包含get函数,get函数返回的值就是计算属性的值,计算属性会被代理为Vue对象实例的属性。
如果想要修改计算属性的值,就必须在计算属性中的对象中添加set方法,并实现实现set方法,如果不添加setter,那么在修改计算属性时就会报错。
<script>
Vue.config.productionTip = false;
vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
computed: {
fullName() {
console.log('执行了getter');
return this.firstName+this.lastName;
}
}
})
</script>
简写方式只能读取,不能进行修改,如果想对计算属性进行修改,就不能使用简写方式,必须使用完整写法,并添加和实现setter
9、监视属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<h2>今天的天气是{{info}}</h2>
<button @click="changeWeather">点我改变天气</button>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
isHot: true
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽';
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
},
watch: {
isHot: {
immediate: true,
handler(newValue,oldValue) {
console.log('isHot发生了改变',newValue,oldValue);
}
}
}
})
</script>
</body>
</html>
监视属性是写在watch之后的,采用对象的形式,对象中必须包含一个handler()函数,监视属性名就是需要监视的属性的名字,在被监视的属性发生改变时,就会调用handler函数,并会将新值和旧值作为参数自动传入
另外,除了handler函数之外,监视属性对象中还可以指定其他的值,例如immediate,如果设置为true,那么,在页面刚被加载之时就会执行一次handler函数
- 通过调用Vue对象实例中的$watch函数实现监视属性
<script>
Vue.config.productionTip = false;
const vm = new Vue()
vm.$watch('isHot',{
immediate: true,
handler(newValue,oldValue) {
console.log('isHot发生了改变',newValue,oldValue);
}
});
</script>
$watch需要传入两个参数,第一个就是需要监视的属性,第二个是一个对象,该对象需要包含一个handler函数,当然也可以指定其他的额外属性,例如immediate,可以让监视属性立即调用一次handler函数。
注意:监视属性不只是能监视data中定义的属性,计算属性他也可以监视。
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
isHot: true,
number: {
a: 1,
b: 1
}
}
watch: {
'number.a': {
handler(newValue,oldValue) {
console.log("a的值发生了改变");
}
}
}
})
</script>
在监视一个对象属性中的某个属性时,需要写全属性名,并使用引号括起来
- 深度监视:在监视某个对象时,其对象中的属性发生变化也会被监视到
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
isHot: true,
number: {
a: 1,
b: 1
}
}
watch: {
number: {
deep: true,
handler() {
console.log('number发生了变化');
}
}
}
})
</script>
要实现深度监视,只需要在监视属性对象中添加deep属性,并设置其为true
10、绑定样式
10.1、绑定class
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.basic{
border: solid 1px;
}
.red-text{
color: red;
}
.back{
background-color: black;
}
.border{
border:5px solid blue;
}
</style>
</head>
<body>
<div id="root">
<div class="basic" :class="mood" @click="changeStyle">{{name}}</div>
<div class="basic" :class="arr">{{name}}</div>
<div class="basic" :class="classObj">{{name}}</div>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
name: 'qymlxin',
mood: 'red-text',
arr: ['red-text','back','border'],
classObj: {
'red-text': true,
back: true,
border: true
}
},
methods: {
changeStyle() {
this.mood = 'border';
}
}
})
</script>
</body>
</html>
-
字符串写法,适用于:样式的类名不确定,需要动态指定 -
数组写法,适用于:要绑定的样式个数不确定,名字也不确定 -
对象写法,适用于:要绑定的样式个数确定,名字也确定,但要动态决定用不用
10.2、绑定style
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<div :style="styleObj1">{{name}}</div>
<div :style="styleArr">{{name}}</div>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
name: 'qymlxin',
styleObj1: {
color: 'red'
},
styleObj2: {
backgroundColor: 'black'
},
styleArr: [
{
color: 'red'
},
{
backgroundColor: 'black'
}
]
}
})
</script>
</body>
</html>
- 绑定style样式,对象写法
- 绑定style样式,数组写法,不常用
11、条件渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<h2>n的值为:{{n}}</h2>
<button @click="n++">点我n+1</button>
<template v-if="n == 1">
<h2>1</h2>
<h2>2</h2>
<h2>3</h2>
</template>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
n: 0
}
})
</script>
</body>
</html>
注意事项:
- 使用v-else和v-else-if时,其一组标签不能分开,必须放在一起
- tempate标签必须配合v-if使用,与v-show配合是不起作用的
- v-show只是暂时隐藏了标签,而v-if在不成立的情况下是直接不添加标签
- 在需要频繁改变页面上的标签显示与否时,建议使用v-show,因为它不用频繁向页面添加标签,而只是改变标签的display属性的值,可以节省性能
12、v-for遍历
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<div>
<ul>
<li v-for="(value,index) in persons" :key="index">{{value}}-{{index}}</li>
</ul>
</div>
<div>
<ul>
<li v-for="(value,key) in cars" :key="key">{{key}}-{{value}}</li>
</ul>
</div>
<div>
<ul>
<li v-for="(value,index) in str" :key="key">{{value}}-{{index}}</li>
</ul>
</div>
<div>
<ul>
<li v-for="(value,index) in 5" :key="key">{{value}}-{{index}}</li>
</ul>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
persons: ['a','b','c'],
cars: {
name: '奥迪A5',
color: '红色',
count: '123'
},
str: 'hellp'
}
})
</script>
</body>
</html>
- 遍历数组:
(value,index) in persons ,其中value是数组的值,index是数组下标 - 遍历对象:
(value,key) in cars ,其中value是对象中的属性值,key是属性的名字 - 遍历字符串:
(value,index) in str ,其中value是字符串中的字符,index是字符所在的下标 - 遍历指定次数:
(value,index) in 5 ,其中value是从1开始递增的整数,index是从0开始的下标
:key指定的是遍历项的唯一标识,是用于虚拟dom进行diff对比算法时使用的对比标识
13、列表过滤
13.1、监视属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<div>
<input type="text" v-model="serchWord">
<ul>
<li v-for="p in filterPer">{{p.name}}-{{p.age}}</li>
</ul>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
serchWord: '',
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:'男'}
],
filterPer: []
},
watch: {
serchWord: {
immediate:true,
handler(value) {
this.filterPer = this.persons.filter((p)=>{
return p.name.indexOf(value) != -1;
});
}
}
}
})
</script>
</body>
</html>
使用监视属性,必须要指定immediate为true,否则会出现页面初次加载不会显示任何项目,只有在输入框输入了内容之后才会显示
13.2、计算属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<div>
<input type="text" v-model="serchWord">
<ul>
<li v-for="p in filterPer">{{p.name}}-{{p.age}}</li>
</ul>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
serchWord: '',
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: {
filterPer() {
return this.persons.filter((p)=>{
return p.name.indexOf(this.serchWord) != -1;
});
}
}
})
</script>
</body>
</html>
计算属性在初次访问和所依赖的属性发生改变时会自动重新执行计算属性中的getter并返回新的值
13.3、列表排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<div>
<input type="text" v-model="serchWord" placeholder="请输入姓名">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="p in filterPer">{{p.name}}-{{p.age}}</li>
</ul>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
serchWord: '',
sortType:0,
persons: [
{id:'001',name:'马冬梅',age:29,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:25,sex:'男'}
]
},
computed: {
filterPer() {
let arr = this.persons.filter((p)=>{
return p.name.indexOf(this.serchWord) != -1;
});
if(this.sortType) {
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age;
});
}
return arr;
}
}
})
</script>
</body>
</html>
14、Vue添加响应式属性
14.1、模拟Vue监测数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
let data = {
name: 'qymlxin',
address: '四川'
}
const obs = new Observer(data);
let vm = {};
vm._data = data = obs;
obs.__obs__ = obs;
function Observer(obj) {
const keys = Object.keys(obj);
keys.forEach((key)=>{
Object.defineProperty(this,key,{
get() {
return obj[key];
},
set(value) {
console.log(`${key}被改了,解析模板,生成虚拟DOM......这里就是解析数据的地方`);
obj[key] = value;
}
})
});
}
</script>
</body>
</html>
14.2、Vue.set()方法的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root">
<h2>名字:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="showAge">点我显示年龄</button>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
person: {
name: 'qymlxin',
}
},
methods: {
showAge() {
Vue.set(this.person,'age',21);
}
}
})
</script>
</body>
</html>
==注意:==Vue.set()方法只能给data配置项中的对象属性添加属性,不能够给data或者Vue实例对象添加属性
vm.$set(vm.person,'age',21); 也可以实现上述操作
l
Document
<div id="root">
<h2>名字:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="showAge">点我显示年龄</button>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
person: {
name: 'qymlxin',
}
},
methods: {
showAge() {
//三个参数分别是:添加位置,属性名,属性值
Vue.set(this.person,'age',21);
}
}
})
//vm.$set(vm.person,'age',21);
</script>
```
==注意:==Vue.set()方法只能给data配置项中的对象属性添加属性,不能够给data或者Vue实例对象添加属性
vm.$set(vm.person,'age',21); 也可以实现上述操作
|