vue的基础学习记录

  1. 1. 安装Vue
    1. 1.1. 1.直接用< script >引入
    2. 1.2. 2.npm安装Vue脚手架 (配合命令行工具)
      1. 1.2.1. 脚手架文件架构
  2. 2. Hello world
  3. 3. Vue模板语法介绍
    1. 3.1. 插值语法
    2. 3.2. 指令语法
  4. 4. 数据绑定
    1. 4.1. 单向数据绑定
    2. 4.2. 双向数据绑定
  5. 5. MVVM模型
  6. 6. 数据代理
  7. 7. 事件处理
    1. 7.1. 事件修饰符
    2. 7.2. 键盘事件
  8. 8. 计算属性
  9. 9. 监视属性
  10. 10. class和style的绑定样式
    1. 10.1. 绑定class样式
    2. 10.2. 绑定style样式
  11. 11. 条件渲染
  12. 12. 列表渲染
    1. 12.1. 基本用法
    2. 12.2. key的作用和原理
    3. 12.3. 列表过滤
  13. 13. Vue检测数据原理
    1. 13.1. 如何监测对象
    2. 13.2. Vue.set
    3. 13.3. 如何监视数组中的数据
  14. 14. 指令
  15. 15. Vue生命周期
    1. 15.1. 1、创建前(beforeCreate)
    2. 15.2. 2、创建后(created)
    3. 15.3. 3、挂载前(beforeMount)
    4. 15.4. 4、挂载后(mounted)
    5. 15.5. 5、更新前(beforeUpdate)
    6. 15.6. 6、更新后(updated)
    7. 15.7. 7、销毁前(beforeDestroy)
    8. 15.8. 8、销毁后(destroyed)
  16. 16. 组件
    1. 16.1. 非单文件组件
    2. 16.2. 单文件组件

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

1
npm install -g @vue/cli

2.创建项目

1
vue create xxxx

3.启动项目

1
npm run serve

[注] 如果下载缓慢可以配置镜像 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">
// 设置为 false 以阻止 vue 在启动时生成生产提示。
Vue.config.productionTip = false;

// 创建Vue示例
new Vue({
el: '#root', // el用于当前Vue用于那个容器,一般因为css选择器字符串。
data: {
name: 'world'
}
});

</script>
</body>
</html>

注: Vue实例与容器必须一一对应

Vue模板语法介绍

插值语法

1
{{ js表达式 }}

指令语法

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">
// 设置为 false 以阻止 vue 在启动时生成生产提示。
Vue.config.productionTip = false;

// 创建Vue示例
new Vue({
el: '#root', // el用于当前Vue用于那个容器,一般因为css选择器字符串。
data: {
name: 'world',
url: 'http://www.baidu.com'
}
});

</script>
</body>
</html>

数据绑定

Vue 中有两种绑定方式

单向数据绑定

1
v-bind:

双向数据绑定

只能用于表单类元素

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">
// 设置为 false 以阻止 vue 在启动时生成生产提示。
Vue.config.productionTip = false;

// 创建Vue示例
new Vue({
el: '#root', // el用于当前Vue用于那个容器,一般因为css选择器字符串。
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
},
// 修改age值时调用
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="函数名"
// 需要在Veu中的methods配置项添加
methods:{
函数名(event){
// event 事件对象
//函数内容
}
}

传参

1
2
3
4
5
6
7
8
// 指令语法
@click="函数名(val)"
// 如果想传event 可以用 $event
methods:{
函数名(val){
//函数内容
}
}

事件修饰符

格式

1
@click.事件修饰符="函数名"
  • prevent:阻止默认事件

  • stop:阻止事件冒泡

  • once:事件只会触发一次

  • capture:使用事件捕获模式

  • self:只有event.target是当前操作元素时才会触发

  • passive: 事件默认行为立即执行,无需等待事件回调执行完毕

键盘事件

keyup 和keydown

别名

1
@keyup.别名
  • 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">
// 设置为 false 以阻止 vue 在启动时生成生产提示。
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
},
// 可以不写
// set(val){
// }
}
}
})

简写(当只考虑读取不需要修改时可以简写)

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)
}
// 初始化时调用handler
// immediate:true
}
}

或者后续配置

1
2
3
4
5
6
7
8
9
10
vm.$watch('监视属性',{
// 新值和旧值
handler(newValue,oldValue){
console.log(newValue,oldValue)
}
// 初始化时调用handler
// immediate:true
// 深度监视
// deep: true
})

简写:当只有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">
// 设置为 false 以阻止 vue 在启动时生成生产提示。
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
}
// 创建一个监视实例对象,用于监视data中属性的变化
const obs = new Observer(data)
// 准备一个vm实例对象
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 )

指令

  • v-bind : 单向绑定解析表达式

  • v-model : 双向数据绑定

  • v-for : 遍历

  • v-on : 绑定事件监听

  • v-if : 条件渲染

  • v-else-if : 条件渲染

  • v-else : 条件渲染

  • v-show : 条件渲染

  • v-text : 向其所在的节点插入文本内容

  • v-html : 向其所在的节点插入文本内容 (支持结构的解析)

  • v-cloak : 配合css使用,用display:none让未经解析的模板不在页面中展示

  • v-once : 在第一次渲染后就视为静态内容了

  • v-pre : 跳过其所在节点的编译过程

自定义指令

  • 在 directives 配置项中定义 ( bind,inserted,update )

Vue生命周期

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
<extval> </extval>

单文件组件

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>

到此基础学习完毕