vue学习笔记
安装Vue
1.直接用< script >引入
直接引用 https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js
或引入官方其他文件
1
| <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
|
可以根据提示选择是否下载Vue的开发者工具
2.npm安装Vue脚手架 (配合命令行工具)
1.全局安装@vue/cli
2.创建项目
3.启动项目
[注] 如果下载缓慢可以配置镜像 npm config set registry 镜像网址
脚手架文件架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| |- node_modules |- public | |- favicon.ico: 页签图标 | |- index.html: 主页面 |- src | |- assets: 存放静态资源 | | |- logo.png | |- components: 存放所有组件 | | |- HelloWorld.vue | |- App.vue: 汇总所有组件 | |- main.js: 入口文件 |- .gitignore: git版本忽略的配置 |- babel.config.js: babel的配置文件 |- package.json: 应用包的配置文件 |- package-lock.json: 包版本控制文件 |- README.md: 应用描述文件 |- vue.config.js: vue脚手架的配置文件
|
Hello world
创建一个Vue实例,通过某些配置项与容器相关联。
el : el用于当前Vue用于那个容器,一般因为css选择器字符串。
data : 用于存储数据对象,用于为 el 指定的容器去使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <!DOCTYPE html> <html> <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>01_初识Vue</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body>
<div id="root"> <h1> Hello {{name}} </h1> </div>
<script type="text/javascript"> Vue.config.productionTip = false;
new Vue({ el: '#root', data: { name: 'world' } });
</script> </body> </html>
|
注: Vue实例与容器必须一一对应
Vue模板语法介绍
插值语法
指令语法
1
| v-bind: 属性 = js表达式 (绑定) == 可以简写为 ==> :属性 = js表达式
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <!DOCTYPE html> <html> <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>模板语法</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body>
<div id="root"> <h1> 插值语法 </h1> <h1> Hello {{name}} </h1> <hr> <h1> 指令语法 </h1> <a v-bind:href="url"> 百度 </a> <a :href="url"> 百度 </a> </div>
<script type="text/javascript"> Vue.config.productionTip = false;
new Vue({ el: '#root', data: { name: 'world', url: 'http://www.baidu.com' } });
</script> </body> </html>
|
数据绑定
Vue 中有两种绑定方式
单向数据绑定
双向数据绑定
只能用于表单类元素
1
| v-model:value = js表达式 ==简写==> v-model = js表达式
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <!DOCTYPE html> <html> <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>数据绑定</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body>
<div id="root"> 单向数据绑定<input type="text" :value="name" > <br/> 双向数据绑定<input type="text" v-model:value="name"> </div>
<script type="text/javascript"> Vue.config.productionTip = false;
new Vue({ el: '#root', data: { name: '数据', } });
</script> </body> </html>
|
MVVM模型
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。微软的WPF带来了新的技术体验,如Silverlight、音频、视频、3D、动画……,这导致了软件UI层更加细节化、可定制化。同时,在技术层面,WPF也带来了 诸如Binding、Dependency Property、Routed Events、Command、DataTemplate、ControlTemplate等新特性。MVVM(Model-View-ViewModel)框架的由来便是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架。它立足于原有MVP框架并且把WPF的新特性糅合进去,以应对客户日益复杂的需求变化。
数据代理
了解 Object.defineProperty 方法可以通过配置项修改age的一些属性
1 2 3 4 5 6 7 8 9
| let person = { name: '张三', sex: '男' }
Object.defineProperty(person,'age',{ value:18, get });
|
注意的配置项
1 2 3 4 5 6 7 8
| get(){ return 18 },
set(value){ console.log(value) }
|
数据代理: 通过一个对象代理对另一个对象的操作
vue中的data数据通过vm对象,对_data里面的数据做数据代理操作
事件处理
-
click: 点击
-
scroll: 滚动条
-
whell: 鼠标滚轮
-
keydown: 键盘按下
-
keyup: 键盘抬起
-
blur: 失去焦点
1 2 3 4 5 6 7 8 9
| v-on:click="函数名" ==简写==> @click="函数名"
methods:{ 函数名(event){ } }
|
传参
1 2 3 4 5 6 7 8
| @click="函数名(val)"
methods:{ 函数名(val){ } }
|
事件修饰符
格式
键盘事件
keyup 和keydown
别名
-
enter: 回车
-
delete: 删除
-
esc: 退出
-
space: 空格
-
tab: 换行
-
up: 上
-
down: 下
-
left: 左
-
right: 右
[注]支持链式调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <!DOCTYPE html> <html> <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>事件处理</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body>
<div id="root"> <h2> {{ name }} </h2> <button @click.once="showInfo"> Hello </button> <button @click="showInfo1($event,'Hello1')"> Hello1 </button> <hr> <input type="text" placeholder="按下回车提示输入" @keydown.enter="showInfo2"> </div>
<script type="text/javascript"> Vue.config.productionTip = false;
const vm = new Vue({ el:"#root", data:{ name:"this is name" }, methods:{ showInfo(event){ alert('Hello'); }, showInfo1(event,val){ alert(val); }, showInfo2(e){ console.log(e.target.value) } } })
</script> </body> </html>
|
计算属性
通过已有的属性计算而来,在Vue实例中的computed配置项定义
以对象方式配置,需要一个get函数
1 2 3 4 5
| <input type="text" v-model="a"> <hr> <input type="text" v-model="b"> <hr> <h2>{{c}}</h2>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const vm = new Vue({ el:"#root", data:{ a:"", b:"" }, computed:{ c:{ get(){ return this.a + this.b }, } } })
|
简写(当只考虑读取不需要修改时可以简写)
1 2 3
| c(){ return this.a + this.b }
|
监视属性
当监视属性变化时handler才会调用,Vue实例中的watch配置项定义
1 2 3 4 5 6 7 8 9 10
| watch:{ '监视属性':{ handler(newValue,oldValue){ console.log(newValue,oldValue) } } }
|
或者后续配置
1 2 3 4 5 6 7 8 9 10
| vm.$watch('监视属性',{ handler(newValue,oldValue){ console.log(newValue,oldValue) } })
|
简写:当只有handler配置项时可以简写
1 2 3 4 5
| watch:{ '监视属性'(newValue,oldValue){ console.log(newValue,oldValue) } }
|
或者后续配置
1 2 3
| vm.$watch('监视属性',function(newValue,oldValue){ console.log(newValue,oldValue) })
|
class和style的绑定样式
绑定class样式
运用 v-bind:class=“class属性” 进行绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <div id="root"> <div class="bs" :class="vc" @click="fun1" ></div> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", data:{ vc: "", idx: 0 }, methods:{ fun1(){ this.vc = "class" + this.idx this.idx = (this.idx + 1) % 3 } } }); </script>
|
:class 可以用值、数组或者对象(对象里的kye为class名,value为boolean值)
绑定style样式
同class,可以用:style=""来进行绑定一样可以使用值。数组、对象,我推荐用对象写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <div id="root"> <div class="bs" :style="styleObj" @click="fun2" ></div> </div> <script type="text/javascript"> Vue.config.productionTip = false; const vm = new Vue({ el:"#root", data:{ size:10, styleObj:{ borderRadius: '10px' } }, methods:{ fun2(){ this.size += 5 this.styleObj.borderRadius = this.size + 'px' } } }); </script>
|
条件渲染
v-show = “boolean值” , 未移除DOM元素,修改 display: none 实现
v-if = “boolean值” , 直接移除DOM元素 (后面可以跟着 v-else-if 和 v-else ) (可以配合 template 标签使用)
列表渲染
v-for 和 key
基本用法
1
| <li v-for="person in persons" :key="person.id">{{person.name}} - {{person.age}}</li>
|
1 2 3 4 5 6 7
| data:{ persons:[ {id:'000',name:'张三',age:18}, {id:'001',name:'李四',age:19}, {id:'002',name:'王五',age:20} ] }
|
key的作用和原理
key 是对应的唯一标识,可以通过 ((person,index) in persons) 获取对应下标index
如果不写key,vue默认用index作为唯一标识
vue 通过key来对列表进行渲染,如果数据发生变化时通过key来进行对比,如果key一样就比较里面的DOM,不一致就替换,一样就复用。如果没有找到key就重新生成一个新的DOM
如果用 li 标签里拥有其他DOM节点,如: a 、 input 、h1 … 等 不建议使用index标识,因为在复用时不会追随原始DOM节点,如节点顺序更换时不仅效率低,也可能会产生其他问题。
列表过滤
利用js数组里的 filter 添加判断过滤,然后在计算属性或者监听属性添加相关处理即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <div id="root"> <h2>人员列表</h2> <input type="text" placeholder="请输入名字" v-model="keyWord"> <ul> <li v-for="person in filpersons" :key="person.id">{{person.name}} - {{person.age}}</li> </ul> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", data:{ persons:[ {id:'000',name:'张三',age:18}, {id:'001',name:'李三',age:19}, {id:'002',name:'王五',age:20}, {id:'003',name:'李五',age:20} ], filpersons:[], keyWord:"" }, methods:{ }, watch:{ keyWord:{ immediate:true, handler(val){ this.filpersons = this.persons.filter((p)=>{ return p.name.indexOf(val) !== -1 }) } } } }); </script>
|
Vue检测数据原理
Vue 会监视data中所有层次的数据
如何监测对象
Vue拿到data时会对其进行加工,通过setter实现监视,且要在new Vue时就传入要监视的数据,类似原理如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| let data = { val1: "a", val2: 1 }
const obs = new Observer(data)
vm = {} vm._data = data = obs function Observer(obj){ const keys = Object.keys(obj) keys.forEach((k) => { Object.defineProperty(this,k,{ get(){ return obj[k] }, set(){ obj[k] = val } }) }) }
|
Vue.set
如果后添加的属性想拥有响应式,可以利用Vue提供的API
Vue.set(target,key,val) 或 vm.$set(target,key,val)
可以去官网了解更详细的信息
如何监视数组中的数据
-
调用原生对应的方法对数组进行更新
-
重新解析模板,进行页面更新
所以如果要修改数组,可以调用那7个方法( push,pop,shift,unshift,splice,sort,reveres )
指令
自定义指令
Vue生命周期

从上面这幅图中,我们可以看到vue生命周期可以分为八个阶段,分别是:
beforeCreate(创建前)、created(创建后)、beforeMount(挂载前)、mounted(挂载后)、beforeUpdate(更新前)、updated(更新后)、beforeDestroy(销毁前)、destroyed(销毁后)
下面我们就来分别看看vue生命周期的这八个阶段:
1、创建前(beforeCreate)
在组件实例初始化完成之后立即调用。数据刚开始创建,此时还无法通过Vue实例获得_data中的内容和methods中的方法。
2、创建后(created)
在组件实例处理完所有与状态相关的选项后调用。已经完成数据检测和数据代理的初始化,已经可以访问_data和methods。
3、挂载前(beforeMount)
在组件被挂载之前调用。此时还无法得到具体的DOM元素,但挂载的根节点已经创建。
4、挂载后(mounted)
在组件被挂载之后调用。将Vue编译过后的DOM插入到页面上,至此初始化完毕,一般在此进行异步请求。
5、更新前(beforeUpdate)
在组件即将因为一个响应式状态变更而更新其DOM之前调用。此时数据以更新,但DOM中的数据还未保持同步。
6、更新后(updated)
在组件因为一个响应式状态变更而更新其DOM之后调用。在这一阶段DOM会和更改过的内容同步。
7、销毁前(beforeDestroy)
在一个组件实例被销毁之前调用。当我们不在需要vue操纵DOM时,就需要销毁Vue,也就是清除vue实例与DOM的关联,就可以调用destroy销毁Vue。此时vue中的对象依然可以访问,一般在此执行一些销毁退出工作。
8、销毁后(destroyed)
在一个组件实例被销毁之后调用。
组件
非单文件组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const ext = Vue.extend({ template:` <div> <h2>{{ extval }}</h2> </div> `, data(){ return{ extval:"组件" } } }) Vue({ el:"#root", components:{ extval } })
|
简写
1 2 3 4 5 6 7 8 9 10 11 12
| const ext = { template:` <div> <h2>{{ extval }}</h2> </div> `, data(){ return{ extval:"组件" } } }
|
然后在html直接使用标签
单文件组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <template> <div> <div class="demo">{{val}}</div> </div> <!-- 组件的结构 --> </template>
<script> // 组件交互相关数据的代码 export default { name:'MyT', data(){ return{ val: "单文件组件" } } } </script>
<style> /* 组件的样式 */ .demo{ background: rgb(255, 0, 0); } </style>
|
到此基础学习完毕