vue是什么?
一套用于构建用户界面的渐进式JavaScript框架。
渐进式:Vue可以自底向上逐层的应用。
- 简单应用:只需一个轻量小巧的核心库。
- 复杂应用:可以引入各式各样的Vue插件。
Vue的特点
- 采用组件化模式,提高代码复用率、且让代码更好维护。
- 声明式编程,让编程人员无需操作DOM,提高开发效率。
- 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点。
地址
- Vue官网地址: Vue.js
- Githup地址:https://github.com/vuejs/vue
一、安装Vue
1.1 使用 <script> 标签引入
直接下载引入,Vue会被注册为一个全局变量。
官网可以下载两种版本:开发版本和生产版本。
区别:
1.开发版本:包含完整的警告和调试模式
2.生产版本:删除了警告,33.46KB min+gzip
也可以使用 cdn 引入【加速】
对于制作原型或学习,可以这样使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
浏览器的 console 的报的提示信息
提示1:提示可以安装 vue 的开发者调试工具。
提示2:Vue.config 是一个对象,包含 Vue 的全局配置。
里面默认的配置属性 productionTip 默认是true,改为false,就可以关闭生产提示。
方法:修改配置。
<script> Vue.config.productionTip = false; // 阻止 vue 在启动时生成生产提示 </script>
1.2 NPM 引入
一般使用npm引入是需要和命令行工具(Vue CLI)一起使用。
命令: npm install vue
最稳定的版本
二、初识Vue
2.1 创建Vue实例
<!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>Document</title>
<link rel="icon" href="../image/logo.svg">
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象。
2. root 容器里面的代码依然符合html规范,只不过混入了一些特殊的Vue语法。
3. root容器的代码被称为【vue模板】
4. Vue实例和容器是一一对应的。
5. 真是开发中只有一个Vue实例,并且会配合着组件一起使用。
6. {
{xxx}} 中的 xxx 要写js表达式,且 xxx 可以自动读取到 data 中的所有属性。
7.一旦data中的数据发生改变,那么页面中用到该数据的地方会自动更新。
注意区分:js 表达式 和 js代码(语句)
1.表达式:一个表达式会产生一个值,可以放在一个需要值的地方。
(1)a
(2)a+b
(3)demo(1)
(4)x === y? 'a':'b'
2.js代码(语句)
(1)if(){}
(2)for()
-->
<!-- 准备一个容器 -->
<div id="root">
<h1>Hello,{
{name}}</h1>
</div>
<script>
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
var obj = { name: 'll' };
// 创建 Vue 实例
const x = new Vue({
el: '#root', // el 用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串,可以使用使用 el: document.getElementById('root'); 来指定容器。
// data 中用于存储数据,数据供 el 所指定的容器去使用。暂时写为一个对象。
data: obj
})
// 可以使用 x.$el 来获取绑定元素
console.log(x.$el); // div#root
// 可以 x.$data.name 来获取 name 的值,也可以直接使用 x.name来获取,两者是相等的。
console.log(x.name); // ll
console.log(x.$data); // {name: "ll"}
console.log(x.$data.name === x.name); // true
console.log(x.$data._property); // undefined
</script>
</body>
</html>
el
类型:
string | Element
限制:只在用
new
创建实例时生效。详细:提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器(#root),也可以是一个 HTMLElement 实例(document.getElementById('root'))。
在实例挂载之后,元素可以用
vm.$el
访问。
data
类型:
Object | Function
限制:组件的定义只接受
function
。详细:
Vue 实例的数据对象。Vue 会递归地把 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对象,原型上的 property 会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。
一旦观察过,你就无法在根数据对象上添加响应式 property。因此推荐在创建实例之前,就声明所有的根级响应式 property。
实例创建之后,可以通过
vm.$data
访问原始数据对象。Vue 实例也代理了 data 对象上所有的 property,因此访问vm.a
等价于访问vm.$data.a
。以
_
或$
开头的 property 不会被 Vue 实例代理,因为它们可能和 Vue 内置的 property、API 方法冲突。你可以使用例如vm.$data._property
的方式访问这些 property。当一个组件被定义,
data
必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果data
仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供data
函数,每次创建一个新实例后,我们能够调用data
函数,从而返回初始数据的一个全新副本数据对象。如果需要,可以通过将
vm.$data
传入JSON.parse(JSON.stringify(...))
得到深拷贝的原始数据对象。
2.2 初识 Vue 总结
- 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象。
- root 容器里面的代码依然符合html规范,只不过混入了一些特殊的Vue语法。
- root容器的代码被称为【vue模板】
- Vue实例和容器是一一对应的。
- 真是开发中只有一个Vue实例,并且会配合着组件一起使用。
- { {xxx}} 中的 xxx 要写js表达式,且 xxx 可以自动读取到 data 中的所有属性。
- 一旦data中的数据发生改变,那么页面中用到该数据的地方会自动更新。
三、Vue核心
3.1 模板语法
3.1.1 插值语法
{ {xxx}} xxx 是js表达式,且可以直接访问到data中所有的属性。
3.1.2 指令语法
v-???
<body>
<!--
Vue模板语法有2大类:
1.插值语法
功能:用于解析标签体内容
写法:{
{xxx}} xxx 是js表达式,且可以直接读取到data中所有的属性。
2.指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件....)
举例:v-bind:href="xxx" 或 简写为 :href="xxx", xxx同样要写js表达式,且可以直接读取到data中的所有属性。
备注:Vue 中有很多的指令,且形式都是 v-??? 此处只是用 v-bind: 举例。
-->
<div id="root">
<h1>插值语法</h1>
<h3>你好,{
{name}}</h3>
<hr>
<h1>指令语法</h1>
<a v-bind:href="url" x="hello">百度</a>
<a :href="url" x="hello">百度</a>
</div>
<script>
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
const vm = new Vue({
el: '#root',
data: {
name: 'll',
url: 'https://www.baidu.com'
}
})
</script>
</body>
Vue模板语法有2大类:
1.插值语法
功能:用于解析标签体内容
写法:{ {xxx}} xxx 是js表达式,且可以直接读取到data中所有的属性。
2.指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件....)
举例:v-bind:href="xxx" 或 简写为 :href="xxx", xxx同样要写js表达式,且可以直接读取到data中的所有属性。
备注:Vue 中有很多的指令,且形式都是 v-??? 此处只是用 v-bind: 举例。
3.2 数据绑定
3.2.1 单向数据流绑定
单向绑定(v-bind):数据只能从data流向页面
3.2.2 双向数据流绑定
双向绑定(v-model): 数据不仅能从data流向页面,还可以从页面流向data
备注:
(1)双向绑定一般都应用在表单类元素上(如:input、select...)
(2)v-model:value 可以简写为 v-model,因为v-model默认收集的就是value的值。
<!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>
<link rel="icon" href="../image/logo.svg">
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
Vue中有2种数据绑定方式:
1.单向绑定(v-bind):数据只能从data流向页面
2.双向绑定(v-model): 数据不仅能从data流向页面,还可以从页面流向data
备注:
(1)双向绑定一般都应用在表单类元素上(如:input、select...)
(2)v-model:value 可以简写为 v-model,因为v-model默认收集的就是value的值。
-->
<div id="root">
<!-- 普通写法 -->
单向数据绑定:
<input type="text" v-bind:value="name">
<br> 双向数据绑定:
<input type="text" v-model:value="name">
<hr>
<!-- 简写 -->
单向数据绑定:
<input type="text" :value="name">
<br> 双向数据绑定:
<input type="text" v-model="name">
<!-- 如下代码是错误的,因为v-model只能应用在表达类元素上(输入类元素) -->
<!-- <h2 v-model:x="name"></h2> -->
</div>
<script>
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
const vm = new Vue({
el: '#root',
data: {
name: 'll'
}
})
</script>
</body>
</html>
3.3 el 与 data的两种写法
3.3.1 el 的两种写法
el的2种写法
- new Vue 时候配置el属性。
- 先创建Vue实例,随后再通过 vm.$mount('#root') 指定el的值。
注意:如果是已经配置好了 $mount() 可以获取到vm实例。
const vm = new Vue({
// el: '#root', // 第一种写法
data: { name: 'll' }
})
vm.$mount('#root'); // 第2种写法
3.3.2 data的两种写法
data2种写法
(1)对象式
(2)函数式
如何选择:目前哪种方式都可以,在组件中,必须使用函数式,否则会报错。
<body>
<!--
data与el的2种写法
1.el有2种写法
(1) new Vue 时候配置el属性。
(2) 先创建Vue实例,随后再通过 vm.$mount('#root')指定el的值。
2.data2种写法
(1)对象式
(2)函数式
如何选择:目前哪种方式都可以,在组件中,必须使用函数式,否则会报错。
3.一个重要的原则:
由Vue管理的函数,一定不要使用箭头函数(this指向window)。
-->
<div id="root">
<h1>你好,{
{name}}</h1>
</div>
<script>
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
// el的两种写法
// const vm = new Vue({
// // el: '#root', // 第一种写法
// data: { name: 'll' }
// })
// // 第2种写法
// vm.$mount('#root');
// console.log(vm);
// data的2种写法
new Vue({
el: '#root',
// data的第一种方式:对象式
data: { name: '11' },
// data的第二种方式:函数式
// data: function () {
// return {
// name: 'll'
// }
// }
// 函数简写
// data() {
// console.log(this); // this指向Vue实例
// return {
// name: 'll'
// }
// }
})
</script>
</body>
3.2.3 注意
一个重要的原则:
由Vue管理的函数,一定不要使用箭头函数(this指向window)。
3.4 MVVM
虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm
(ViewModel 的缩写) 这个变量名表示 Vue 实例。
MVVM模型:
M:模型(Model):对应 data 中的数据
V:视图(View):模板
VM:视图模型(ViewModel):Vue实例兑现
观察发现:
- data中所有的属性,最后都出现在了vm上。
- vm身上的属性 及 Vue 原型上所有属性,在Vue模板中都可以直接使用。
从图上看出:
VM 其实是 View 和 Model 之间数据传递的桥梁,这便是Vue做的事情,主要功能是数据绑定(将数据绑定在dom中) 和 DOM 监听(监听dom的数据变化)。
3.5 数据代理
3.5.1 回顾Object.defineProperty方法
1.Object.defineProperty() 的参数
Object.defineProperty(参数1, 参数2, 参数3);
- 参数1:劫持的对象。
- 参数2:劫持对象中的属性(可以不存在)。
- 参数3:是个对象{},对象中有控制对象属性的一些属性
{
value: 18, // 属性值
enumerable: true, // 控制属性是否可以枚举(遍历),默认值是 false
writable: true, // 控制属性是否可以被修改,默认值为 false
configurable: true, // 控制属性是否可以被删除,默认值为 false
get(){ //属性被读取是,该函数被调用,返回值就是age的值 },
set(value){ // 属性被修改时,该函数被调用,value为修改后最新的值 }
}
1.Object.defineProperty() 案例
<body>
<script>
let number = 18;
let obj = {
name: 'll',
sex: '男'
};
Object.defineProperty(obj, 'age', {
value: 18,
enumerable: true, // 控制属性是否可以枚举(遍历),默认值是 false
writable: true, // 控制属性是否可以被修改,默认值为 false
configurable: true, // 控制属性是否可以被删除,默认值为 false
// 当读取 obj 的属性age时,get函数(getter)就会被调用,且返回值就是age的值。
get() {
console.log('读取age属性');
},
set(value) {
console.log('修改属性');
number = value;
}
})
console.log(obj);
obj.age = 20;
console.log(Object.keys(obj));
console.log(obj);
delete obj.age;
console.log(obj);
console.log(obj.age);
console.log(number);
</script>
</body>
3.5.2 何为数据代理
数据代理:通过对一个对象代理对另一个对象中的属性的操作(读/写)。
<body>
<!-- 数据代理:通过对一个对象代理对另一个对象中属性的操作(读/写) -->
<script>
let obj = { x: 100 };
let obj2 = { y: 50 };
Object.defineProperty(obj2, 'x', {
get() {
return obj.x;
},
set(value) {
obj.x = value;
}
})
console.log(obj);
console.log(obj2);
</script>
</body>
3.5.3 Vue中的数据代理
data 对应vm上的 _data 和 vm上添加的属性一致。
数据代理图示:
<body>
<!--
1.Vue中的数据代理:
通过vm对象来代理data对象中的属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data的数据
3.基本原理:
通过 Object.defineProperty() 把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
在 getter/setter 内部去操作(读/写)data中对应的属性。
-->
<div id="root">
<h2>学校名称:{
{school}}</h2>
<h2>学校地址:{
{adress}}</h2>
</div>
<script>
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
const vm = new Vue({
el: '#root',
data: {
school: 'hc',
adress: 'hy'
}
})
</script>
</body>
3.6 事件处理
3.6.1 事件的基本使用
v-on:click="demo" 不写括号,函数内的第一个参数其实就是事件对象。
v-on:click="demo($event)" 传参,可以使用 $event 传递事件对象。
v-on: 可以简写,即语法糖 @
函数需要定义在 methods 中, 且不能为箭头函数,只能使用普通函数的写法。
实际上也是添加到了实例对象 vm 上。
<body>
<!--
事件的基本使用:
1.使用 v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名。
2.事件的回调需要配置在 methods 对象中,最终会在vm上。
3.methods 中配置的函数,不要用箭头函数!否则this就不是vm了。
4.methods 中配置的函数,都是被vue所管理的函数,this的指向是vm 或 组件实例对象。
5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参。
-->
<div id="root">
<h2>欢迎来看{
{name}}</h2>
<!-- <button v-on:click="showInfo">点我提示</button> -->
<!-- 简写方式 -->
<button @click="showInfo1">点我提示1(不传参)</button>
<!-- 传参 -->
<button @click="showInfo2($event,666)">点我提示2(传参)</button>
</div>
<script>
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
const vm = new Vue({
el: '#root',
data: {
name: '广场剧'
},
methods: {
showInfo1(event) {
console.log(event); // 事件对象
console.log(event.target.innerText); // 事件对象
console.log(this); // 此处this为vm
alert('hi~~');
},
showInfo2(event, number) {
console.log(event, number); // 事件对象
alert('hi~~hi~~hi');
}
},
})
</script>
</body>
3.6.2 事件修饰符
写法:@click.prevent="showInfo" 阻止默认事件。
事件修饰符 | 描述 |
.prevnet | 阻止默认事件 |
.stop | 阻止事件冒泡 |
.once | 事件只能触发一次 |
.capture | 使用事件的捕获模式 |
.self | 只有 event.target 是当前操作的元素时才触发事件 |
.passive | 事件的默认行为立即执行,无需等待事件回调执行完毕 |
scroll: Element.scroll() - Web API 接口参考 | MDN
wheel: 滚轮事件 - Web API 接口参考 | MDN
scroll 是页面滚动条滚动会触发的事件,而wheel是鼠标滚轮滚动会触发的事件。
一旦滚动条到底部后,滑动鼠标滚轮继续滚动,wheel就会一直触发,而scroll不会触发。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">