vue2基础(多文件)

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

一、安装 Vue 与 Vue Devtools

  • 安装 vue

  1. 通过vue 文档官网下载vue 开发版本将下载的 js 文件放到项目 js 目录中。

  2. 通过<script>标签直接导入:

<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.0/vue.js"></script>

或压缩版:

<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.0/vue.min.js"></script>

  • 安装 vue Devtools

获取谷歌浏览器插件

获取火狐浏览器插件

获取Edge 浏览器插件

直接安装插件即可

二、Hello World 案例

{{str}}
HelloWorld案例

Hello World 案例

html
1
<div id="demo1">{{str}}</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo1',
data:{
str:'Hello World'
}
})
css
1

三、案例分析

  1. 当两个容器含有同一类名时:

{{str}}
{{str}}
Hello

Vue 的 Hello World 案例分析

html
1
2
3
4
5
6
<div class="demo2">
<div>{{str}}</div>
</div>
<div class="demo2">
<div>{{str}}</div>
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'.demo2',
data:{
str:'Hello World'
}
})
css
1

容器与 Vue 实例为一对一关系,且 Vue 实例有且只有一个。

中的语句写 js 表达式,且语句可以读取到 data 中的属性。

data 中的属性发生变化,容器中语句引用的地方也会更新。

四、模板语法

(一)、插值语法

你好,{{name}}
插值语法

插值语法

html
1
2
3
<div id="demo3">
<div>你好,{{name}}</div>
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo3',
data:{
name:'Tom',
}
})
css
1

  • v-bind:可简写为:

  • 插值语法用于标签体内容

(二)、指令语法

指令语法

指令语法

html
1
2
3
<div id="demo4">
<a v-bind:href="url">跳转到百度</a>
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo4',
data:{
url:'https://baidu.com/'
}
})
css
1

  • 指令语法用于解析标签,如标签属性,标签体内容,绑定事件。

五、数据绑定

(一)、单向数据绑定

单向数据绑定

单向数据绑定

html
1
2
3
<div id="demo5">
<input type="text" :value="str">
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo5',
data:{
str:'数据单向绑定'
}
})
css
1

  • 修改 v-bind 绑定的值时,data 里的值不会一同改变。
    v-bind

(二)、双向数据绑定

双向数据绑定

双向数据绑定

html
1
2
3
<div id="demo6">
<input type="text" v-model:value="str"> <!-- 使用控制台中Vue开发者工具可以看到数据变化 -->
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo6',
data:{
str:'数据双向绑定'
}
})
css
1

  • v-model 只能用于表单类元素如<h2 v-model:x="name"></h2>是错误的形式

  • 修改 v-model 绑定的值时,data 里的值也会一同改变。

  • v-model:value 可简写为 v-model,因为 v-model 默认值为 value

v-model

六、el 与 data 的两种写法

(一)、el 绑定的第二种方法

你好,{{name}}
el绑定的第二种写法

通过$mount

html
1
2
3
<div id="demo7">
<div>你好,{{name}}</div>
</div>
javascript
1
2
3
4
5
6
const vue = new Vue({
data:{
name:'Tom',
}
})
vue.$mount('#demo7');
css
1

(二)、data的第二种写法

你好,{{name}}
data的第二种写法

通过函数返回

html
1
2
3
<div id="demo8">
<div>你好,{{name}}</div>
</div>
javascript
1
2
3
4
5
6
7
8
var vm = new Vue({
el:'#demo8',
data:function(){
return {
name:'Tom'
}
}
})
css
1

  • 不要使用箭头函数(匿名函数)

七、Object.defineProperty()

Object.defineProperty()用于为对象添加属性。

1
2
3
4
let person = {
name: "Tom",
sex: "male",
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Object.defineProperty(person, "age", {
//为person添加age属性值为18。
value: 18, //值为18
enumerable: true, //使属性可被遍历,默认false
writable: true, //使属性可被修改,默认false
configurable: true, //使属性可被删除,默认false
get: function () {
//每当读取person的age属性时,都会调用,默认返回值为value
return value + 1;
},
//简写为
get() {
return value + 1;
},
set(value) {
//每当person的age属性被修改时会被调用
return value + 1;
},
});

八、事件

(一)、事件处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button v-on:click="show1">非简写点击事件</button>
<button @click="show2">简写点击事件</button>
<script>
new Vue({
el: "element",
data: {},
method: {
show1(e) {
//e代表点击事件
},
show2(e) {},
},
});
</script>

(二)、事件修饰符

1
<a href="https://baidu.com" @click.prevent="showInfo">提示信息</a>

修饰符:

  • prevent: 阻止默认事件。

  • stop: 阻止事件冒泡。

  • once: 事件只触发一次。

  • capture: 使用事件的捕获模式。

  • self: 只有 event.target 是当前操作的元素才触发事件。

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

(三)、键盘事件

1
2
<input type="text" @keydown.enter="show" />
<input type="text" @keyup.enter="show" />
  • 常用键盘按键:

别名名称
enter回车
delete删除
esc退出
space空格
tab换行
up
down
left
right
  • 未提供别名的按键可用原始 key 值绑定,但要转换为短横线命名如:CapsLock->caps-lock

  • 系统修饰键:ctrl,alt,shift,win

    1. 配合 keyup 使用:按下修饰键同时按下其他键,再放开其他键。
    2. 配合 keydown 使用
  • 通过键码(不推荐)如:keydown.13 为回车。

  • 通过Vue.config.keyCodes.自定义名 = 键码这样自定义的名称就和键码联系起来了。

九、计算属性

1
2
3
4
5
6
7
8
9
10
new Vue({
el: ".el",
data: {},
computed: {
comfn: {
get() {},
set(value) {},
},
},
});

计算属性:

  • 定义:要使用的属性需要通过已有属性计算得来。

  • 原理:借助Object.defineproperty方法提供的gettersetter

  • get执行时机:

    1. 初次读取
    2. 依赖变化
  • 优势:与 method 相比,内有缓存机制,效率高。

  • 计算属性要被修改必须通过写set函数响应。

当计算属性只需要get时,可写为:

1
2
3
4
5
6
7
new Vue({
el: ".el",
data: {},
computed: {
comfn() {}, //get函数
},
});
{{full}}
计算属性

返回姓名组合

html
1
2
3
4
5
6
<div id="demo9">
<input type="text" v-model:value="x">
<input type="text" v-model:value="m">
<div>{{full}}<div>
</div>
</div></div>
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var vm = new Vue({
el:'#demo9',
data:{
x:"张",
m:"三"
},
computed:{
full:{
get(){
return this.x+"-"+this.m;
}
}
}
})
css
1

十、监视属性

1
2
3
4
5
6
7
8
9
10
11
12
13
new Vue({
el: ".el",
data: {
wafn: "",
},
watch: {
wafn: {
//监视wafn属性
immediate: false, //初始化时是否调用handler
handler(newValue, oldValue) {},
},
},
});

或通过 vm 对象进行添加

1
2
3
4
5
6
7
8
9
10
var vm = new Vue({
el: ".el",
data: {
wafn: "",
},
});
vm.$watch("wafn", {
immediate: false, //初始化时是否调用handler
handler(newValue, oldValue) {},
});

深度监视

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Vue({
el: ".el",
data: {
nums: {
a: 1,
b: 1,
},
},
watch: {
nums: {
//监视nums属性
handler(newValue, oldValue) {},
},
},
});

如果使用以上形式会检测不到 num 内 a,b 值的变化,需要为监视函数 nums 添加 deep:true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new Vue({
el: ".el",
data: {
nums: {
a: 1,
b: 1,
},
},
watch: {
nums: {
//监视nums属性
deep: true, //深度监视
handler(newValue, oldValue) {},
},
},
});
  • watch 默认不监视对象内部值的改变(单层)

  • 使用 deep:true 候,可以检测对象内部值的变化(多层)

  • Vue 可以检测对象内部改变,但 watch 默认不行

十一、绑定 class 样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="root">
<div :class="cl"></div>
<div :class="cl1"></div>
<div :style="{fontSize: fsize+'px'}"></div>
</div>
<script>
new Vue({
el: "#root",
data: {
cl: "className",
cl1: ["className1", "className2", "className3"],
fsize: 10,
},
});
</script>

对象形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="root">
<div :class="clObj"></div>
<div :style="stObj"></div>
</div>
<script>
new Vue({
el: "#root",
data: {
clObj: {
className1: true,
className2: false, //只有值为true的类名才会在div上使用
},
stObj: {
fontSize: "40px",
},
},
});
</script>

十二、条件渲染

(一)、v-show

1
2
<div v-show:"true"></div>
<div v-show:"false"></div>

(二)、v-if

1
2
3
<div v-if:"true"></div>
<div v-else-if:"false"></div>
<div v-if:"false"></div>

区别:v-show 为 false 时会将模板解析,但会添加 dispaly:none 属性,所以不显示。

v-if 为 false 时则直接不解析。

  • v-if 与 v-else-if 是一组 if 语句,中间不能插其他标签。

十三、列表渲染

  • {{p.id}}-{{p.name}}-{{p.age}}
  • {{index}}-{{o}}
  • {{index}}-{{t}}
  • {{n}}
列表渲染

三种渲染:数组,对象,字符串,次数

html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="demo10">
<ul>
<li v-for="p in persons" :key="p.id">{{p.id}}-{{p.name}}-{{p.age}}</li>
</ul>
<ul>
<li v-for="(o,index) in obj" :key="index">{{index}}-{{o}}</li>
</ul>
<ul>
<li v-for="(t,index) in str" :key="index">{{index}}-{{t}}</li>
</ul>
<ul>
<li v-for="(n) in 3" :key="index">{{n}}</li>
</ul>
</div>
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Vue({
el:'#demo10',
data:{
persons:[
{id:'1',name:'person1',age:'20'},
{id:'1',name:'person2',age:'21'},
{id:'1',name:'person3',age:'22'}
],
obj:{
data1:"test",
bool: true,
},
str:"hello"
},
})
css
1

每个key都应唯一
v-for可以从列表,对象,字符串中去除对象或属性。

十四、列表过滤

  • {{p.name}}-{{p.age}}-{{p.sex}}
列表过滤

列表过滤案例

html
1
2
3
4
5
6
<div id="demo11">
<input type="text" v-model:value="keyWord">
<ul>
<li v-for="(p,index) of filpersons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}</li>
</ul>
</div>
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
new Vue({
el:'#demo11',
data:{
persons:[
{id:'001',name:'马冬梅',age:30,sex:'女'},
{id:'002',name:'周冬雨',age:31,sex:'女'},
{id:'003',name:'周杰伦',age:18,sex:'男'},
{id:'004',name:'温兆伦',age:19,sex:'男'}
],
keyWord='',
filpersons:[ ]
},
watch:{
keyWord:{
immediate:true,
handler(val)
{
this.filpersons = this.persons.filter((p)=>{
return p.name.indexOf(val)!==-1;
})
}
}
}
});
css
1

十五、Vue 监视数据

image-20220713190744008

图片来源:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=37

十六、过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="root">
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.3/dayjs.min.js"</script>
<h3>时间是:{{time | timeFormater}}</h3>
</div>
<script>
new Vue({
el:"#root",
dara:{
time:1657717090991
},
filters:{
timeFormater(val){
return dayjs(val).format('YYYY年MM月DD日 HH:mm:ss')
}
}
})
</script>

在管道符后写过滤函数例:

格式化前时间是:{{time}}

格式化后时间是:{{time | timeFormater}}

过滤器

过滤器

html
1
2
3
4
5
<div id="demo12">
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.3/dayjs.min.js"></script>
<h3>格式化前时间是:{{time}}</h3>
<h3>格式化后时间是:{{time | timeFormater}}</h3>
</div>
javascript
1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:'#demo12',
data:{
time:1657720756624 //时间戳
},
filters:{
timeFormater(val){
return dayjs(val).format('YYYY年MM月DD日 HH:mm:ss')
}
}
});
css
1

全局过滤器:

1
2
3
4
Vue.filter("过滤器名", function () {
函数体;
return 结果;
});

十七、内置指令

(一)、v-text

v-text

v-text

html
1
2
3
<div id="demo13">
<div v-text="txt"></div>
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo13',
data:{
txt:'这是文本内容'
}
});
css
1

  • v-text 向所在节点中渲染文本

  • v-text 会替换节点中原有的内容,而插值语法不会

(二)、v-html

v-html 支持结构解析而 v-text 不支持

v-html

v-html

html
1
2
3
<div id="demo14">
<div v-html="html"></div>
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo14',
data:{
html:'<h3>v-html插入的内容</h3>'
}
});
css
1

注意

在网站上动态渲染 html 是非常危险的,不要将 v-html 使用在用户提交内容上

(三)、v-cloak

解决由于网速等问题,导致 vuejs 不能及时加载,使未经渲染过的模板直接出现在网站上,页面闪动。

1
2
3
4
5
6
7
<style>
[v-cloak] {
//属性选择器
display: none;
}
</style>
<h3 v-cloak>v-cloak的元素</h3>

当 vuejs 加载完成后,会自动将页面中的 v-cloak 属性删除,这样被隐藏的界面就可以显示出来了。

(四)、v-once

1
2
3
4
5
6
7
8
9
10
11
<div id="demo16">
<div v-once>{{n}}</div>
</div>
<script>
new Vue({
el: "#demo16",
data: {
n: 1,
},
});
</script>

当标签含有属性 v-once 后,则模板渲染一次后就成为静态资源不再重新渲染,即使源数据发生了改变。

(五)、v-pre

当标签添加 v-pre 后,该标签的模板就不会再被解析,一般用于优化代码。

{{str}}
v-pre

v-pre

html
1
2
3
<div id="demo15">
<div v-pre>{{str}}</div>
</div>
javascript
1
2
3
4
5
6
new Vue({
el:'#demo15',
data:{
str:'测试内容'
}
});
css
1

十八、自定义指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="root">
<h2 v-x="n"></h2>
</div>
<script>
new Vue({
el: "#root",
data: {
n: 99,
},
directives: {
x(element, binding) {
//简写形式
element.innerHTML = binding.value * 2;
},
},
});
</script>
{{n}}
自定义指令

将值放大两倍

html
1
2
3
4
5
<div id="demo17">
<div>{{n}}</div>
<div v-x="n"></div>
<button @click="n++">点击加一</button>
</div>
javascript
1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:'#demo17',
data:{
n:0
},
directives:{
x(element,binding){ //简写形式
element.innerHTML=binding.value*2
}
}
});
css
1

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
<div id="root">
<h2 v-x="n"></h2>
</div>
<script>
new Vue({
el: "#root",
data: {
n: 99,
},
directives: {
x: {
bind(element, binding) {
//绑定时调用
element.innerHTML = binding.value * 2;
},
inserted(element, binding) {
//插入时调用
element.focus();
},
update(element, binding) {
//更新时调用
element.innerHTML = binding.value * 2;
},
},
},
});
</script>

全局指令:

1
2
3
4
5
Vue.directive("指令名", {
bind(element, binding) {},
inserted(element, binding) {},
update(element, binding) {},
});

十九、生命周期(重要)

生命周期指生命周期函数,是 Vue 在不同时刻调用的一些特殊函数,生命周期名不可被改变。

生命周期图示

Vue 实例生命周期

流程:

1
2
graph TB
beforeCreate --> created --> beforeMount --> mounted --> beforeUpdate --> updated --> beforeDestroy --> destroyed

生命周期详细内容:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=50

二十、组件

(一)、非单文件组件

非单文件组件

非单文件组件示例

html
1
2
3
4
<div id="demo18">
<school></school> <!-- 组件别名 -->
<student></student>
</div>
javascript
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
const school = Vue.extend({
template:`
<div>
<div>{{name}}</div>
<div>{{add}}</div>
</div>
`,
data(){ //注意使用函数式
return {
name:"testSchoolName",
add:"testSchoolAdd"
}
}
})
const student = Vue.extend({
template:`
<div>
<div>{{name}}</div>
<div>{{age}}</div>
</div>
`,
data(){ //注意使用函数式
return {
name:"testStuName",
age:"testStuAge"
}
}
})
new Vue({
el:'#demo18',
components:{
school,
student //这是简写方法,组件别名与组件名相同
// 组件别名:组件名
}
})
css
1

(二)、组件的嵌套

组件的嵌套

组件的嵌套示例

html
1
2
3
<div id="demo19">
<app></app>
</div>
javascript
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
const school = Vue.extend({
template:`
<div>
<div>{{name}}</div>
<div>{{add}}</div>
</div>
`,
data(){ //注意使用函数式
return {
name:"testSchoolName",
add:"testSchoolAdd"
}
}
})
const student = Vue.extend({
template:`
<div>
<div>{{name}}</div>
<div>{{age}}</div>
</div>
`,
data(){ //注意使用函数式
return {
name:"testStuName",
age:"testStuAge"
}
}
})
const app = Vue.extend({
template:`
<div>
<school></school>
<student></student>
</div>
`,
components:{
school,
student
}
})
new Vue({
el:'#demo19',
components:{
app
}
})
css
1

二十一、重要内置关系

https://www.bilibili.com/video/BV1Zy4y1K7SH?p=59

vue与vueComponent的关系