目录
1. vue 介绍
1.1 概念
vue 是一套用于构建用户界面的渐进式JavaScript框架
vue 可以自底向上逐层的应用
1.2 发明人
vue 是由尤玉溪 在2013年发布的,2015年发布vue1.0.0,2016年发布vue2.0.0,2020年发布3.0.0
1.3 vue 特点
- 采用组件化模块,提高代码复用率,让代码更好地维护
- 声明式编码,无需直接操作BOM,提高开发效率
- 采用虚拟DOM+优秀的Diff 算法,尽量复用DOM节点
1.4 学前需掌握知识
ES6语法规范、ES6模块化、包管理、原链、原型链、数组常用方法、axios、promise
2. 初始Vue
使用vue 必须创建一个vue 实例,并传入一个配置对象
<body>
<!-- 容器 -->
<div id="root">
<!-- {{}}插值 -->
<h1>hello,{{name}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; //阻止vue启动时生产提示
// 创建vue实例
new Vue({
//el是element的简称,el 用于指定为哪个容器指定服务,值通常为css选择器修饰符
el: '#root',
// data中用于存储数据,数据供el的容器使用,值暂时先写对象
data: {
name: 'lisa',
}
});
</script>
</body>
- 上面代码中,root 容器代码符合 html 语法规范,另外加入了一些特殊的vue 语法(‘{{}}’ 插值)
- root 容器的代码称 vue 模板
- 一个vue实例只能对应一个容器(取第一个容器)
- 一个容器只能被一个vue容器接管
- 简单来说就是实例和容器 一 一对应
- 插值{{}} 里面可放JS表达式,可以读取到data中所有的属性
- data数据改变,模板用到数据也会自动更新
- 实际开发中只有一个 vue 实例,并且搭配组件使用
区分: js 表达式 和 js 代码(语句)
- 表达式: 一个表达式会生成一个值,可以放任意地方
- 代码(语句):if(){},for(){}
3. vue 模板语法
3.1 差值语法{{}}
- 功能: 用于解析标签体内容
- 语法: {{xxx}} ,xxxx 会作为 js 表达式解析
3.2 指令语法
- 功能: 解析标签属性、解析标签体内容、绑定事件
- 举例:v-bind:href = 'xxxx' ,xxxx 会作为 js 表达式被解析 (v-bind:可以简写 :)
<body>
<div id="demo">
<!-- 1.插值语法 -->
<p id="p">good morning, {{name}} </p>
<!--2. 指定语法 -->
<a v-bind:href="url">点我去百度</a>
</div>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
name: 'Harry', //1.插值语法
url: 'http://www.baidu.com', //2. 指定语法
}
})
</script>
</body>
4. 数据绑定
4.1 单向绑定
- 语法:v-bind:href ="xxx" 或简写为 :
- 特点:数据只能从 data 流向页面
4.2 双向数据绑定
- 语法:v-mode:value="xxx" 或简写为 v-model="xxx" 因为v-model默认收集的是value值
- 特点:数据不仅能从 data 流向页面,还能从页面流向 data
- 只能用于表单元素
<body>
<div id="demo">
<!-- 普通写法 -->
单向数据绑定: <input type="text" v-bind:value="name"> //单向绑定
双向数据绑定: <input type="text" v-model:value="age"> //双向绑定
<!-- 简写 -->
单向数据绑定: <input type="text" :value="name">
双向数据绑定: <input type="text" v-model="age">
</div>
<script type="text/javascript">
Vue.config.productionTip = false; //阻止vue启动时生产提示
new Vue({
el: '#demo',
data: {
name: 'jojio',
age: 18,
}
})
</script>
</body>
5. el 和 data两种写法
5.1 el
-
new vue时配置了el属性;el: 'xxx',
-
先创建vue实例,在用v.$mount('xxx') 指el得值
两种都可以使用
const v = new Vue({
// el第一种写法
el: '#demo',
});
// el第二种写法
v.$mount('#demo'); //mount是挂载意思
5.2 data
-
对象式:date:{ }
-
函数式:data:function(){ return }
- 由vue管理的函数,千万不要写箭头函数,写了this指向就不是vue实例对象了!!
- 学习到组件时,一定要用函数式写法,避免了数据污染;不能用对象式,会影响其他数据
const e = new Vue({
// data 第一种写法:对象式
/* data: {
name: 'lisa',
} */
// data 第二种写法:函数式
data: function () {
return {
name: 'pi',
}
}
6.MVVM 技术
- M:模型(Model) :对应 data 中的数据
- V:视图(View) :模板
- VM:视图模型(ViewModel) : Vue 实例对象
vue没有完全遵循 MVVM 模型,但是设计也受到了它的启发。因此在文档中经常会使用 vm
(ViewModel 的缩写) 这个变量名表示组件实例。
data中的属性(数据)放在viewmodel中
vm 的属性以vue原型上所有的属性,在vue魔板中可以直接使用
6. 数据代理
6.1 回调Object.defineProperty
Object.defineProperty方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法:Object.defineProperty(obj, prop, descriptor)
obj:
要定义属性的对象。prop:
要定义或修改的属性的名称或 Symbol 。descriptor:
要定义或修改的属性描述符。
方法的属性:
- enumerable:控制属性是否可以枚举,默认不可以枚举(不可遍历)
- writable: 控制属性是否可以修改
- configurable: 控制属性可以被删除
- 注意:这些属性默认值都为false
- get(): getter 方法:读取并返回属性值
- set(): setter 方法,修改属性值,并返回修改的值
6.2 理解数据代理
数据代理:通过一个对象代理另一个对象中属性的操作(读写)
let obj = { x: 100 };
let obj2 = { y: 200 };
Object.defineProperty(obj, 'x', {
get() {
return obj.x;
},
set(value) {
obj2.x = value;//通过obj.x可修改obj2.x的值
}
})
6.3 vue 中的数据代理
基本原理:
- 通过defineProperty()把data对象所有属性添加到vm
- 为每一个添加到vm的属性,指定一getter和setter
- 在getter和setter内操作读写data中对应的属性
优点:方便操作数据
7. 事件处理
7.1 事件绑定
写法一:<button v-on:click="showInfo">点击有惊喜</button>
简单写法: <button @click="showInfo">点击有惊喜</button>
<body>
<div id="demo">
<h2>欢迎来到{{name}}的学习</h2>
<!-- 不带参数 -->
<button v-on:click="showInfo">点击有惊喜</button>
<!-- <button @click="showInfo">点击有惊喜</button> -->
<!-- 带参数 -->
<button @click="showInfo2(66,$event)">开心就点击</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; //阻止vue启动时生产提示
const vm = new Vue({
el: '#demo',
data: {
name: 'Vue',
},
methods: {
showInfo(event) {
alert('hi~要加油呀')
},
showInfo2(number, event) {
console.log(number, event);
}
}
});
</script>
</body>
注意:方法要写在 vue 里的methods对象中
7.2 事件修饰符
- prevent:阻止默认事件(常用)
- stop:阻止事件冒泡(常用)
- once:事件只触发一次(常用)
- capture:使用事件的捕获模式
- self:只有
event.target
是当前操作的元素时才触发事件- passive:事件的默认行为立即执行,无需等待事件回调执行完毕
写法:
<!-- 阻止单击事件继续冒泡 -->
<a @click.stop="doThis"></a>
7.3 键盘修饰符
补充es6知识:e.target.value 获取的是触发事件输入得值
- 回车:enter
- 删除:delete (捕获“删除”和“退格”键)
- 退出:esc
- 空格:space
- 换行:tab (特殊,必须配合keydown去使用)
- 上:up
- 下:down
- 左:left
- 右:right
系统修饰键(ctrl、alt、shift、meta ) 使用:
- 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
- 配合keydown使用:正常触发事件
7.4 总结
- 修饰符可以连着写多个(如@click.prevent.stop=)
- Vue.config.keyCodes.自定义键名=键码, 可以自定义按键别名(不推荐)
8. 计算属性
vue 里面的data 里面的对象是属性,用属性去变化成一个全新的属性,叫计算属性
<!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">
<script type="text/javascript" src="./js/vue.js"></script>
<title></title>
</head>
<!-- 输入一个姓和名 ,全名会同时更新姓名-->
<body>
<div id="demo">
姓:<input type="text" v-model="first"><br>
名: <input type="text" v-model="last"><br>
全名:<span>{{full}}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; //阻止vue启动时生产提示
new Vue({
el: '#demo',
data: {
first: 'zhang',
last: 'san',
},
computed: {
// 完整写法
// full: {
// get() {
// return this.first + this.last
// },
// set(value) {
// const arr = value
// this.first = arr[0]
// this.last = arr[1]
// }
// }
// 简写,确定只读不改的情况下使用
full() {
return this.first + this.last;
}
}
});
</script>
</body>
</html>
- 定义要用的属性不存在,通过已有的属性计算出的
- 原理:用object.defineproperty方法提供的getter和setter
- get函数执行情况:初次读取时;依赖的数据发生改变时
- 优势:与method实现比,内部有缓存机制(复用),效率高,调试方便
- 备注:计算属性最终出现在vm上,直接读取使用即可;如果计算属性要修改,必须写上set函数,且set依赖发生变化
9. 监视属性watch
handler(newvalue,oldvalue){ }
两种写法:
1.new Vue({ ... watch:{})
2. vm.$watch()
- 可以监视属性和计算属性
- 知道监视对象,就用写法一
- 不知道监视对象,用写法二
- 当属性变化时, 回调函数handler自动调用, 在函数内部进行计算
- 监视的属性必须存在,才能进行监视,如果没有不会报错
9.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">
<script src="../js/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<button @click="changeWeather">切换天气</button>
<hr />
<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">点我让a+1</button>
<h3>b的值是:{{numbers.b}}</h3>
<button @click="numbers.b++">点我让b+1</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#app',
data: {
numbers: {
// 开启深度监视
deep: true,
a: 1,
b: 2,
}
},
methods: {
changeWeather() {
this.innerHTML = "凉爽"
}
},
watch: {
handler() {
console.log("number改变");
},
}
})
</script>
</body>
</html>
- Vue中的watch默认不监测对象内部值的改变(一层)
- 配置deep:true可以监测对象内部值改变(多层)vue.numbers.a
9.2 监视简写
前提是不需要immedia、deep,只有handler,就可以简写
vue 管理的函数不能写箭头函数
watch:{
//1. 正常写法
isHot:{
// immediate:true, //初始化时让handler调用一下
// deep:true,//深度监视
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
//简写
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
}
}
})
//2. 正常写法
vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
deep:true,//深度监视
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
//简写
vm.$watch('isHot', {
handler(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue)
}
})
9.3 watch和computed 对比
区别:
- computed能完成的功能,watch都可以完成。
- watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
- 计算属性多个影响一个时使用,是需要返回值
- 监视属性一个影响多个时使用,是已经存在的属性
两个重要的小原则:
- 被Vue管理的函数写成普通函数,this的指向是vm 或 组件实例对象。
- 不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。否则是this指向window
- 上面两种写法都是为了让his指向vm