Better

  • 主页
  • 随笔
所有文章 友链 关于我

Better

  • 主页
  • 随笔

vue vue基础语法

2020-06-15

vue 是一个渐进式框架

渐进式意味着你可以将 Vue 作为你应用的一部分嵌入其中,带来更丰富的交互体验。可能你的项目本来是拿 jquery 或者原生 js 写的,现在可以一部分一部分换成 vue

vue 全家桶

Core + Vue-router(路由)+Vuex(状态管理)

vue.js 的安装

1.直接 cdn 引入

这里可以参考官方文档

2.下载和引入

在官网找到下载地址,一般使用开发版本

3.NPM 安装

vue 的初了解

vue 的初始用

以前我们通过 jquery 和 原生 js 需要 DOM 操作,也就是在我们第一步需要获取 DOM 元素,然后按照需求对 DOM 元素进行操作,这种是命令式,vue 则是声明式

下面是一个 Vue 程序,展示了 Vue 的响应式

1
2
3
4
5
6
7
8
9
10
11
<div id="app"> 
<h2>{{message}}</h2>
</div>
<script>
const app = new Vue(//{创建 vue 对象,里面
el: '#app', //挂载元素,该属性决定了这个 Vue 对象挂载到哪一个元素
data: { //该属性存储数据
message: 'Hello'
}
})
</script>

结果如下:image-20200615213116055

浏览器执行代码的流程:

  • 先执行 html 代码,显示相对应的 html
  • 当执行到 script 代码的时候,创建 vue 实例,并且对原 HTML 进行解析个修改。
  • 当我们在 script 中添加这样的代码 app.message = 'Hi welcoming’, h2 元素中的 message 的值就会发生变化,这就是一种响应式的体验。(在开发者模式中直接敲代码也可)

vue 展示列表

展示一个更加复杂的数据:数据列表。把从服务器端获取的数组展示到 HTML 中。通过 v-for指令实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="app">
<ul>
<!-- 通过 v-for展示数组 -->
<li v-for="item in fruits">{{item}}</li>
</ul>
</div>

<script>
const app = new Vue({
el: '#app',
data: {
fruits: ['apple', 'pear', 'orange']
}
})
app.fruits.push('cherry')
</script>

当我们加上这样一句代码app.fruits.push('cherry'),页面就会新添加一条 li ,响应式。

计数器案例

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
    <div id="app">
<h2>当前计数: {{counter}} </h2>
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
</div>

<script>
// 把 model 用一个对象存储
const obj = {
counter: 0,
message: '成功'
}
const app = new Vue({
el: '#app',
data: obj ,
methods: {
add: function() {
console.log('add被执行');
// counter++; // counter is not defined
// 这里直接使用cunter是不行的,count 是 app 的一个属性
// app.counter 一般在方法里面 this 指向的是 vue 实例
this.counter++
},
sub: function() {
console.log('sub被执行');
// 三元表达式 用的很好哦
this.counter = this.counter === 0 ? 0 : this.counter--
}
}
})
</script>

新的属性:methods,该属性用于在Vue对象中定义方法。

新的指令:@click, 该指令用于监听某个元素的点击事件,并且需要指定当发生点击时,执行的方法(方法通常是methods中定义的方法)。

@click 是 v-on:click 的语法糖。

Vue 中的 MVVM

MVVM (Model-view -viewmodel)是一种软件架构模式。

Vue的MVVM

image-20200616105318735

  • View层:

    • 视图层
    • 在我们前端开发中,通常就是DOM层。
    • 主要的作用是给用户展示各种信息。
  • Model层:

    • 数据层
    • 数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。
    • 在我们计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。
  • VueModel 层:

    • 视图模型层

    • 视图模型层是 View 和 Model 沟通的桥梁。

    • 一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中

    • 另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。

以上面的计算器为例,分析 MVVC

01-计数器的MVVM
  • view 是 DOM;
  • Model 就是 obj
  • ViewModel 就是我们创建的 Vue 对象实例

mvvc 之间如何工作

  • 首先 ViewModel 通过 Data Binding 让 obj 中的数据实时的在 DOM 中显示。
  • 然后 ViewModel 通过 DOM Listener 来监听 DOM 事件,并且通过 methods 中的操作,来改变 obj 中的数据。

有了 Vue 帮助我们完成 VueModel 层的任务,在后续的开发,我们就可以专注于数据的处理,以及DOM的编写工作了.

创建 Vue 实例传入的 options

我们在创建 vue 实例时候,会传入一个对象 options

1
2
3
new Vue({
// options 对象
})

options

1)el:

  • 类型:string | HTMLElement( document.querySelector() ) el: '#app',

  • 作用:决定之后 Vue 实例会管理哪一个DOM。

2) data:

  • 类型:Object | Function (组件当中data必须是一个函数)

  • 作用:Vue 实例对应的数据对象。

3) methods:

  • 类型:{ [key: string]: Function }

  • 作用:定义属于 Vue 的一些方法,可以在其他地方调用,也可以在指令中使用。

method 和 function 的区别

method是定义在一个对象里面,method是依赖与一个对象的,function是独立与对象的。

4) 生命周期函数:

Vue的生命周期

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

在 vue 不同的生命周期内,可以在生命周期钩子的写函数,进行回调。

image-20200616142411857 image-20200616141947402

制作 vue 简单模板(template)

通过 Vscode 快速创建自定义代码模板,在Vscode中找到首选项 -> 用户代码片段,在输入框内输入html,并点击第一个html.json,在 json 里面我们可以编辑想要的模板。之后输入触发词 ,就可以使用模板。

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
"Html5-Vue": {
"prefix": "vue", //这里规定的是触发模板的关键词,我这里规定触发词为vue
"body": [
"<!DOCTYPE html>",
"<html lang=\"zh-CN\">\n",
"<head>",
"\t<meta charset=\"UTF-8\">",
"\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
"\t<meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">",
"\t<title>Document</title>",
"\t<script src=\"../vue.js\"></script>",
"</head>\n",
"<body>",
"\t<div id=\"app\">$1</div>\n",
"\t<script>",
"\t\tvar vm = new Vue({",
"\t\t\tel: '#app',",
"\t\t\tdata: {},",
"\t\t\tmethods: {}",
"\t\t});",
"\t</script>",
"</body>\n",
"</html>"
],
"description": "快速创建在html5编写的vue模板"//双引号包括的是对模板描述,同时也是你在.html页面输入触发词后,智能提示中出现的对触发词的解释。
}

插值操作

Mustache

如何将 data 中的文本数据,插入到HTML中呢?

可以通过 Mustache 语法(也就是双大括号)。

就像下面这个而例子,data 的数据通过 Mustache 语法插入到 html 中。在 Mustache 语法中我们不仅可以插入简单的属性,还可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="app">
<!-- 插入到标签中 -->
<h2>hello {{message}}</h2>
<!-- 使用两个mustache -->
<h2>{{firstName}} {{lastName}}</h2>
<!-- mustache 里面可以是简单的表达式 -->
<h2> {{counter++}}</h2>
</div>

<script>
var vm = new Vue({
el: '#app',
data: {
message: 'vue',
firstName: 'judy',
lastName: 'Green',
counter: 10
},
});
</script>

v-once

Vue 是响应式变化,但是在某些情况下,我们可能不希望界面随意的跟随改变,使用v-once

v-once

  • 该指令后面不需要跟任何表达式(比如之前的 v-for后面是由跟表达式的)
  • 该指令表示元素和组件 (组件后面才会学习) 只渲染一次,不会随着数据的改变而改变。
1
<h2 v-once>{{message}}</h2> //修改message的值,页面的这个标签不会发生变化

v-html

某些情况下,我们从服务器请求到的数据本身就是一个HTML代码,如果我们直接通过 Mustache语法来输出,会将HTML代码也一起输出。我们希望的是按照HTML格式进行解析,并且显示对应的内容。此时我么需要使用v-html指令。

v-html

  • 该指令后面往往会跟上一个 string 类型
  • 会将 string 的 html 解析出来并且进行渲染

直接将html代码写在Mustache语法里面,页面会把 url 属性都显示出来。

image-20200617171609735
1
2
<h2>{{url}} </h2>
<h2 v-html="url"></h2>

v-text

v-text 作用和 Mustache 比较相似:都是用于将数据显示在界面中,v-text 通常情况下,接受一个 string 类型。

当我们使用 v-text 的时候,如果标签内部也有文字,那么 v-text 指令的文本就会覆盖标签内部的文字。

1
2
<h2 v-text='message'> 初体验</h2> //初体验被覆盖了
<h2>{{message}} 初体验</h2>
image-20200617172143877

v-pre

v-pre 用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。

1
2
<h2>{{message}}</h2>
<h2 v-pre>{{message}}</h2>//显示为 {{message}}

v-cloak

js 卡顿,或者当计数器的时间未到,浏览器可能会直接显然出未编译的Mustache标签 ,这样对用户界面是不友好的 。

cloak: 斗篷

使用方法如下:

1
2
3
4
5
6
7
<style>
[v-cloak] {
display: none;
}
</style>

<h2 v-cloak>{{message}}</h2>

在 vue 解析之前,div 中有一个属性 v-clock,在 vue 解析之后, v-clock 属性就会自动取消。

动态绑定

v-bind

我们除了内容需要动态决定外,属性也希望动态绑定。比如动态绑定a元素的href属性,这个时候,我们可以使用v-bind指令。

v-bind

  • 作用 动态绑定属性
  • 缩写 :

v-bind 用于绑定一个或多个属性值,或者向另一个组件传递props值(这个学到组件时再介绍)

在开发中,有哪些属性需要动态进行绑定呢?

  • 还是有很多的,比如图片的链接src、网站的链接href、动态绑定一些类、样式等等。

比如通过 Vue 实例中的 data 绑定元素的 href。

1
2
3
4
5
6
7
8
9
10
11
12
<div id="app">
<a v-bind:href="link"> Vue.js官网 </a>
</div>

<script>
var vm = new Vue({
el: '#app',
data: {
link: 'https://cn.vuejs.org/index.html'
}
});
</script>
v-bind 语法糖

v-bind有一个对应的语法糖,也就是简写方式

1
<a :href="link"> Vue.js官网 </a>

v-bind 绑定class

绑定class有两种方式:

  • 对象语法

  • 数组语法

对象语法

以前我们直接在 class 里绑定类名,这个类名是死的,不可以动态变化。

通过数组的形式传入多个属性对,然后用 boolean 值判断。true 的时候则保留属性,false 则隐藏属性。

形如 :class="{类名:boolean值 }",这 boolean 值可以是一个变量 isActive(isActive: true) ,也可以是一个等式(:class="{active:isActive == index}" )

在DOM 中 “…” 和 ‘…’ 会被自动解析为字符串,没有加引号就会成为一个变量,类名的写法既可以加引号,也可以不用加,:class="{类名:boolean值 }" 和 :class="{'类名':boolean值 }"。即使css在其他文件夹,当前文档中没有这个类名也是可以的。

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
26
27
28
29
30
31
32
33
34
35
36
<p class='active'> 我是红色嘛</p>

<!-- 用法一:直接通过{}绑定一个类 -->
<p v-bind:class='isActive'> 我是红色嘛</p>

<!-- 用法二:通过判断,传入多个值 -->
<h2 :class="{'active':isActive , 'line':isLine}">Hello World</h2>

<!-- 用法三 :和普通的类同时存在,并不冲突 -->
<h2 class="center" :class="{'active':isActive }">我会居中
</h2>

<!-- 用法四:如果过于复杂,可以放在一个methods或者computed中 -->
<!-- 通过一个方法获得属性 方法要写() -->
<h2 :class="getClasses()">Hello World(通过方法获取属性)</h2>

<button v-on:click='toggleColor'>点击切换颜色</button>
---------
data: {
active: 'active',
isActive: true,
isLine: true
},
methods: {
toggleColor: function() {
this.isActive = !this.isActive;
},
// 所有的变量都要指明this
getClasses: function() {
return {
'active': this.isActive,
'line': this.isLine
}
}

}
数组语法(了解)

数组语法的含义是:class后面跟的是一个数组

1
2
3
4
5
//active 被解析为字符串
<p v-bind:class="['active']"> 我是红色嘛</p>

//active 是变量名
<p v-bind:class="[active]"> 我是红色嘛</p>
案例

点击列表中的哪一项,那么该项的文字变成红色

通过v-for 循环列表并标记每个列表的 index ,v-bind:class 控制红色字体样式是否显示。

原生 js 中实现上面功能都使用排他思想,但是在 vue 中使用指令绑定class,则不需要考虑排他。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app">
<ul>
<li v-for="(meg,index) in movies" :class="{'active':isActive == index } " v-on:click="toggleClor(index)">{{meg}} </li>
</ul>
</div>

<script>
var vm = new Vue({
el: '#app',
data: {
isActive: false,
movies: ['美丽人生', '乱世佳人', '岁月神偷', '阿甘正传', '海贼王']
},
methods: {
toggleClor(index) {
debugger
this.isActive = index;
}
}
});
</script>

v-bind 绑定 style

我们可以利用v-bind:style来绑定一些CSS内联样式。

在写CSS属性名的时候,比如font-size ,我们可以使用驼峰式 (camelCase) fontSize ,或短横线分隔 (kebab-case,记得用单引号括起来) ‘font-size’

绑定class有两种方式:

  • 对象语法

  • 数组语法

对象语法

style 后面跟的是一个对象类型

  • 对象的 key 是 CSS 属性名称

  • 对象的 value 是具体赋的值,值可以来自于 data中 的属性

1
<p :style="{fontSize:fSize + 'px' , background:color}">我是红色,50px</p>
1
2
3
4
data: {
color: 'red',
fontSize: 30
}

如果这个样式需要条件才可以生效(比如点击的时候,字体颜色变为红色),可以使用计算属性。

数组语法

style后面跟的是一个数组类型

  • 多个值以,分割即可

计算属性

我们知道,在模板中可以直接通过插值语法显示一些data中的数据。但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示。

计算属性的基本使用

比如我们有 firstName 和 lastName 两个变量,我们需要显示完整的名称。但是如果多个地方都需要显示完整的名称,我们就需要写多个

我们可以将上面的代码换成计算属性:

我们发现计算属性是写在实例的computed选项中的。计算属性的名字尽量起名词不是动词,因为 它是一个属性。

image-20200621174225809

计算属性的 setter 和 getter

每个计算属性都包含一个getter和一个setter

  • 在上面的例子中,我们只是使用getter来读取。

  • 在某些情况下,你也可以提供一个setter方法(不常用)。

  • 在需要写setter的时候,代码如下:

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
<body>
<div id="app">
<h2>{{fullName}} </h2>
</div>

<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'Kaev',
lastName: 'Red'
},
computed: {
fullName: {
// 只读
get() {
console.log('调用了fullName的get');
return this.firstName + " " + this.lastName
},
// 这里需要传入一个newvalue的形参
set(newValue) {
console.log('调用了fullName的set');
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
}
}
});
</script>

计算属性的缓存

我们可能会考虑这样的一个问题:

methods 和 computed 看起来都可以实现我们的功能,

那么为什么还要多一个计算属性这个东西呢?

原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。而 method 则每次都会调用方法,占内存。

对于这种不会发生变化的 需要计算的 属性,需要使用 computed,而不是 method。

1
2
3
4
5
<!-- 2. 通过计算属性 会把属性缓存起来,一般只调用一次属性里面的函数-->
<h2>{{fullName}} </h2>
<h2>{{fullName}} </h2>
<h2>{{fullName}} </h2>
<h2>{{fullName}} </h2>

虽然一共写了 4 次计算属性,但是只会调用一次。

image-20200622110650835
1
2
3
4
5
<!-- 3.通过method ,每次都会调用该方法-->
<h2>{{getFullName()}} </h2>
<h2>{{getFullName()}} </h2>
<h2>{{getFullName()}} </h2>
<h2>{{getFullName()}} </h2>

一共调用了 4 次,修改属性之后,也会重新调用 4 次。

image-20200622111131116

事件监听

在前端开发中,我们需要经常和用于交互。

这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等。在 Vue 中如何监听事件呢?使用v-on指令

v-on介绍

作用:绑定事件监听器

缩写(语法糖):@

预期:Function | Inline Statement | Object

参数:event

v-on 参数问题

当通过 methods 中定义方法,参数问题:

1.如果该方法不需要额外参数,那么方法后的()可以不添加。

2.如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去

1
2
3
4
5
6
7
8
9
10
11
12
13
 <!-- ++++ 123 -->
<button @click="btn2Click(123)">按钮2</button>

<!-- ++++ undefined -->
<button @click="btn2Click()">按钮2</button>

<!-- ++++ MouseEvent对象  -->
<button @click="btn2Click">按钮2</button>

-----------------
btn2Click(a) {
console.log("++++", a);
}

3.如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
      <!-- ++++ 123 MouseEvent 对象  abc是一个变量-->
<button @click="btn3Click(abc,$event)">按钮3</button>

<!-- ++++ abc MouseEvent 对象 abc是一个字符串-->
<button @click="btn3Click('abc',$event)">按钮3</button>

-------------
data: {
abc: '123'
},
btn3Click(a, event) {
console.log("++++", a, event);
}

v-on修饰符

在某些情况下,我们拿到 event (事件)的目的可能是进行一些事件处理。

Vue提供了修饰符来帮助我们方便的处理一些事件:

  • stop - 调用 event.stopPropagation()。

  • prevent - 调用 event.preventDefault()。

  • {keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。

  • native - 监听组件根元素的原生事件。

  • once - 只触发一次回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 1. 停止冒泡 -->
<div @click="divThis"> aaaa
<button @click.stop="doThis">停止冒泡</button>
</div>

<!-- 2.阻止默认行为 -->
<!-- 点击submit会默认跳转页面,这里是希望点击之后不要跳转执行点击事件的函数 -->
<form action="baidu">
<input type="submit" value="submit" @click.prevent="submitClick">
</form>

<!-- 3.只当事件是从特定键触发时才会触发回调 -->
<!-- 在文本框输入字符时 只有点击enter才会触发事件函数 -->
<input placeholder="点击enter触发" @keyup.enter="onEnter">
<!-- 通过键的ASCII码 -->
<input placeholder="点击enter触发" @keyup.13="onEnter">

<!-- 4.点击回调只会触发一次 -->
<button @click.once="doThis">只执行一次</button>

条件判断

Vue 的条件指令可以根据表达式的值在 DOM 中渲染或销毁元素或组件。例如v-if后面可跟 boolean 值,为 true 的时候渲染元素,为 false 不渲染元素。

1
<h2 v-if="isShow">....<h2>

v-if、v-else-if、v-else这三个指令与 JavaScript 的条件语句if、else、else if 类似。这三个指令不常一起使用,如果出现多分支判断可以写在计算属性里面。

v-if 的原理:

  • v-if 后面的条件为false时,对应的元素以及其子元素不会渲染。

  • 也就是根本没有不会有对应的标签出现在DOM中。

v-if 案例

用户再登录时,可以切换使用用户账号登录还是邮箱地址登录。

问题

如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。

但是按道理讲,我们应该切换到另外一个input元素中了。在另一个input元素中,我们并没有输入内容。为什么会出现这个问题呢?

image-20200623162041240

问题解答:

这是因为 Vue 在进行 DOM 渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。

在上面的案例中,Vue 内部会发现原来的 input 元素不再使用,直接作为 else 中的 input 来使用了。

解决方案:

如果我们不希望 Vue 出现类似重复利用的问题,可以给对应的 input 添加 key ,并且我们需要保证key的不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="app">

<span v-if="type === 'username'">
<label for="">用户账号</label>
<input type="text" placeholder="用户账号" key="uname">
</span>

<span v-else>
<label for="">邮箱地址</label>
<input type="text" placeholder="邮箱地址" key="email">
</span>

<button @click="handToggle">切换类型</button>

</div>

v-show

v-show 的用法和 v-if 非常相似,也用于决定一个元素是否渲染:

v-if和v-show对比

v-if和v-show都可以决定一个元素是否渲染

  • v-if当条件为false时,压根不会有对应的元素在DOM中。

  • v-show当条件为false时,仅仅是将元素的display属性设置为none而已。

开发中如何选择呢?

  • 当需要在显示与隐藏之间切片很频繁时,使用v-show

  • 当只有一次切换时,通过使用v-if

循环遍历

v-for 遍历数组

当我们有一组数据需要进行渲染时,我们就可以使用 v-for 来完成。

v-for的语法类似于JavaScript中的for循环。

格式如下:item in items的形式。

在遍历的过程中,没有使用索引值(下标值),依次从 names 中取出 item,并且在元素的内容中,我们可以使用 Mustache 语法,来使用 item

1
2
3
4
5
<ul>
<li v-for="item in names">
{{item}}
</li>
</ul>

如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢?

语法格式:v-for=(item, index) in items

第一个参数是数组元素,第二个参数是数组下标,与参数名无关(也就是写成 v-for=(index, item) in items),index 里存储的是数组元素而不是下标

1
2
3
4
5
<ui>
<li v-for="(item,index) in names">
{{index}}-{{item}}
</li>
</ui>

v-for 遍历对象

v-for 可以用户遍历对象:

比如某个对象中存储着你的个人信息,我们希望以列表的形式显示出来。

+ html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
     <!--1.在遍历对象的过程中, 如果只是获取一个值, 那么获取到的是value-->
<ul>
<li v-for="item in info"> {{item}}</li>
</ul>

<!--2.获取key和value 格式: (value, key) -->
<ul>
<li v-for="(value,key) in info"> {{key}} - {{value}}</li>
</ul>

<!--3.获取key和value和index 格式: (value, key, index) -->
<ul>
<li v-for="(value,key,index) in info">{{index}} - {{key}} - {{value}}</li>
</ul>
-------------------
data: {
info: {
name: 'why',
age: 18,
height: 1.88
}
},

组件的 key 属性

官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。

为什么需要这个key属性呢(了解)?

这个其实和 Vue 的虚拟 DOM 的 Diff 算法有关系。

比如我们想在一个数组 [ A,B,C,D,E] 的 B 和 C之间插入一个 F。

我们希望是,在 B 和 C 之间添加一个li6 ,并把 F 写进去。

image-20200623174804431

但是事实是,系统把 li3 的值改成 F ,之后依次修改,在末尾添加一个 li6 ,这样性能就非常低

数组渲染之后-在中间插入元素的渲染过程

所以我们需要使用 key 来给每个节点做一个唯一标识

  • Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点
  • key的作用主要是为了高效的更新虚拟DOM

下面是有 key 和没有 key 的区别简图。

image-20200623180106306

因此在使用 v-for 指令的时候,最好绑定 key 属性,并把值设为 item

1
2
3
4
5
<ul>
<li v-for="(item,index) in nums" :key="item">
{{index}} - {{item}}
</li>
</ul>

检测数组更新

因为 Vue 是响应式的,所以当数据发生变化时,Vue 会自动检测数据变化,视图会发生对应的更新。

Vue 中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新。

接下来通对数组 letters ([‘a’, ‘d’, ‘c’, ‘b’])使用下面 7 中常见的数组方法,查看是否是响应式的。

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
//1. push() 从数组尾部添加元素
this.letters.push('aa')
this.letters.push('bb', 'aa', 'cc')

// 2. pop() 删除数组中的最后一个元素
this.letters.pop();

// 3. shift() 删除数组中的第一个元素
this.letters.shift()

//4. unshift() 丛数组头部添加元素
this.letters.unshift('aa')
this.letters.unshift('aa', 'bb', 'ff')

// 5. splice()
// 5.1 删除元素
this.letters.splice(1, 2) //a,d
this.letters.splice(1) //1 后面的所有元素全部删除
// 5.2 替换元素
this.letters.splice(1, 3, 'm', 'l', 'k') //a,m,l,k
// 5.3 插入元素
this.letters.splice(1, 0, 'r', 't') //a,r,t,d,c,b

// 6. sort() 默认从小到大排序
this.letters.sort()

//7. reverse()
this.letters.reverse()

以上 7 种方法都是响应式的,但是通过索引值修改数组中的元素不是响应式的

1
this.letters[0] = 'adfg'; //数组本身发生变化,但是不会渲染到页面

如果我们想要响应式的通过数组下标修改数组的值,可以通过以下两种方法:

1
2
3
4
5
// 1. 通过splice方法改变数组元素值
this.letters.splice(0, 1, 'adfg')

// 2.通过vue的set(要修改的对象, 索引值, 修改后的值)
Vue.set(this.letters, 0, 'adfg')

案例 : 图书购物车

image-20200624143243642

需求:

  1. 把数据渲染到表格里 v-for 每给单元格的数据
    • 是给个单元格设置一个变量,还是通过 item.的方式渲染数据
    • 通过 item. 的方式来渲染数据,因为数据的属性过多,单独设置变量占内存
  2. 购买数量 列,可以 增加和减少数量 v-on:
    • 自己绑定++,–的表达式,还是通过计算属性
    • 因为需要用到点击事件,所以 method ,计算属性使用的仍是 双大括号语法。
    • 减少数量时2,但数量为1,按钮显示为 disabled 不可用
  3. 操作列可以删除整行数据,删除最后一个表格的时候,显示购物车为空。
    • 每行的移除绑定事件让 v-if 为true
    • 删除每行可以通过 删除数组元素达到响应式的删除一行数据
    • table 绑定一个v-if 值为数据的长度,当数据全部删除,v-if 也就为 0 就会不渲染数据。在通过 v-else 显示购物车数据为空
  4. 总价随着操作会发生变化
    • 计算属性

总结 :

  1. 购买数量列的处理
1
2
3
4
<td><button @click="decreace(index)" 
:disabled="item.count <= 1">-</button>
{{item.count}}
<button @click="increace(index)">+</button> </td>
  1. 删除每行的操作
1
2
3
4
delItem(index) {
this.books.splice(index, 1);
console.log(this.books.length)//一共有4个元素,当删除到第4个元素,长度为0
}
  1. vue 和 jquery开发的问题

感受最深的就是响应式,比如删除一行数据,可以通过删除指定 index 的元素。增加和减少商品数量,method 和 computed 的数据都是会相应发生变化的。如果以前的 jquery 删除每行操作的是 dom ,每次商品数量发生变化,都需要重新遍历整个表格的价格和数量进行叠加。

  1. 过滤器 filters()的使用

flilters 的参数就是|前的数据或者方法的返回值

+ html
1
2
3
4
5
6
7
8
9
<td>{{item.price|showPrice}}</td>

-----------

filters: {
showPrice(price) { //这里的price 就是 item.price
return '¥' + price.toFixed(2)
}
}

注意:

vue 中变量和字符串通过有没有引号来区分

1
2
:disabled="'disabled'"://绑定的‘disabled’
disabled="disabled"//绑定的是一个变量

表单绑定 双向绑定

表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。

Vue 中使用 v-model 指令来实现表单元素和数据的双向绑定。

案例的解析:

当我们在输入框输入内容时

因为 input 中的 v-model 绑定了 message ,所以会实时将输入的内容传递给 message,message 发生改变。当 message 发生改变时,因为上面我们使用 Mustache语 法,将message 的值插入到 DOM 中,所以 DOM 会发生响应的改变。

同时 message 值的变化也会引起 input 的 value 的变化。

所以,通过 v-model 实现了双向的绑定。

image-20200628090054196

我们也可以将v-model用于textarea元素

v-model原理

v-model 其实是一个语法糖,它的背后本质上是包含两个操作:

  1. v-bind绑定一个value属性

  2. v-on指令给当前元素绑定input事件

上面的语法如下

1
2
3
4
5
<input type="text" v-model="message">
<!-- 等同于下面 -->
<input type="text" :value="message" @input="message = $event.target.value">

<p>input 标签:{{message}}</p>

v-model + radio

复选框的基础知识

点击 label 的元素可以触发 for 的 input 元素,因此通常用 label 包裹着 input 元素;

当存在多个复选框时,name 属性相同的复选框同时只能选中一个。

1
<label for="male"><input type="radio" name="sex" id="male">男</label>

下面通过 v-model 绑定 radio 的值

  • 我们需要手动添加 value 属性值用于 v-model 绑定
  • 使用 v-model 之后,可以省去 name 属性,多个复选框互斥
+ html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
<label for="male">
<input type="radio" id="male" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" value="女" v-model="sex">女
</label>
<p>{{sex}}</p>
</div>

<script>
const vm = new Vue({
el: '#app',
data: {
sex: '男'
}
});
</script>

v-model + checkbox

复选框分为两种情况:单个勾选框和多个勾选框

单个勾选框:

  • checkbox 的 value 是布尔值,当选中时,value 是 true,未选中是false

  • v-model 即为布尔值。

多个复选框:

  • 当是多个复选框时,因为可以选中多个,所以对应的 data 中属性是一个数组。

  • 当选中某一个时,就会将 input 的 value 添加到数组中。

  • checkbox 的 value 需要指定,否则就是 null

+ 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
26
<div id="app">
<!-- 1.单个勾选框 -->
<label for="check">
<input type="checkbox" id="check" v-model="checked">同意协议
</label>
<p>是否被选中:{{checked}} </p>
<button :disabled="!checked">确定</button>
<br>
<br>

<!-- 2.勾选多个勾选框 -->
<label for="basketball"><input type="checkbox" v-model="hobies" id="basketball" value="篮球" >篮球</label>
<label for="football"><input type="checkbox" v-model="hobies" id="football" value="足球" >足球</label>
<label for="tabletennis"><input type="checkbox" v-model="hobies" id="tabletennis" value="乒乓球" >乒乓球</label>
<p>爱好是:{{hobies}} </p>
</div>

<script>
const vm = new Vue({
el: '#app',
data: {
checked: false,
hobies: []
}
});
</script>

v-model + select

html 知识:在 selet 里添加 multiple 就可以实现多选。

和checkbox一样,select也分单选和多选两种情况。

单选:只能选中一个值。

  • v-model 绑定的是一个值。

  • 当我们选中 option 中的一个时,会将它对应的 value 赋值到 mySelect 中

多选:可以选中多个值。

  • v-model 绑定的是一个数组。

  • 当选中多个值时,就会将选中的 option 对应的 value 添加到数组 mySelects 中

+ 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
26
27
28
29
<div id="app">
<!-- 1.选择一个值 -->
<select v-model="fruit">
<option value="apple"> apple </option>
<option value="pear"> pear </option>
<option value="strawberry"> strawberry </option>
<option value="banana"> banana </option>
</select>
<p>选择的是:{{fruit}} </p>

<!-- 2.选择多个值 -->
<select v-model="frruits" multiple>
<option value="apple"> apple </option>
<option value="pear"> pear </option>
<option value="strawberry"> strawberry </option>
<option value="banana"> banana </option>
</select>
<p>选择的是:{{frruits}} </p>
</div>

<script>
const vm = new Vue({
el: '#app',
data: {
fruit: 'apple',
frruits: []
}
});
</script>

v-model 值绑定

只绑定,就是动态的给value赋值而已:

我们前面的value中的值,都是在定义input的时候直接给定的。

1
<option value="apple"> apple </option>

但是真实开发中,这些input的值可能是从网络获取或定义在data中的。所以我们可以通过v-bind:value动态的给value绑定值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
<!-- 勾选多个勾选框 -->
<label v-for="item in originHobies" :for="item">
<input type="checkbox" v-model="hobies" :id="item" :value="item" >{{item}} </label>

<p>爱好是:{{hobies}} </p>
</div>

<script>
const vm = new Vue({
el: '#app',
data: {
hobies: [],
originHobies: ['basketball', 'football', 'tabletennis', 'bidminton']
},
methods: {}
});
</script>

v-model 修饰符

lazy 修饰符:

默认情况下,v-model 默认是在 input 事件中同步输入框的数据的。也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。同步数据过于频繁。

lazy 修饰符可以让数据在失去焦点或者回车时才会更新。

number 修饰符:

默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。

number 修饰符可以让在输入框中输入的内容自动转成数字类型。image-20200628113521478

trim 修饰符:

如果输入的内容首尾有很多空格,通常我们希望将其去除

trim 修饰符可以过滤内容左右两边的空格

赏

谢谢你请我吃糖果

  • vue

扫一扫,分享到微信

微信分享二维码
leetcode day2
vue vue基础
© 2020 Better
Hexo Theme Yilia by Litten
  • 所有文章
  • 友链
  • 关于我

tag:

  • css
  • js
  • html
  • Python
  • Numpy
  • Pandas
  • vue
  • uml
  • 框架
  • c++
  • git
  • 工具
  • javaee
  • java
  • leetcode
  • 数据库
  • tensorflow
  • 工具类
  • 网页布局
  • RL
  • more
  • 算法
  • summary
  • 计算机组成原理
  • 软件测试
  • 插件
  • jsp
  • 移动端布局
  • 操作系统
  • 微信小程序
  • 计算机网络
  • hobby
  • 机器学习
  • python

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 友情链接1
  • 友情链接2
  • 友情链接3
  • 友情链接4
  • 友情链接5
  • 友情链接6
很惭愧

只做了一点微小的工作
谢谢大家