vue-基础语法和组件化开发

  • A+
所属分类:Web前端
摘要

vue基础语法fullname: {set(), get()}每个计算属性都包含一个getter和一个setter在上面的例子中,我们只是使用getter来读取。

vue基础语法

一. 计算属性

1.1. 计算属性的本质

fullname: {set(), get()}

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

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

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

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

vue-基础语法和组件化开发

1.2. 计算属性和methods对比

计算属性在多次使用时, 只会调用一次.

它是由缓存的

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

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

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

原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。

我们来看下面的代码:

vue-基础语法和组件化开发

1.3. ES6 语法

let/var (定义变量)

vue-基础语法和组件化开发

块级作用域

变量作用域 :

ES5中的var是没有作用域的

ES中的let是有作用域的(if / for)

变量在什么范围内是可用的

var没有作用域限制(会引起一些问题 )

没有块级作用域所引起的问题

没有块级作用域 数据得不到保证,在哪都能修改

const (定义长量)

vue-基础语法和组件化开发

对象字面量增强写法

vue-基础语法和组件化开发

二. 事件监听

2.1. 事件监听基本使用

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

这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等

在Vue中如何监听事件呢?使用v-on指令

v-on介绍

作用:绑定事件监听器

缩写:@

预期:Function | Inline Statement | Object

参数:event

这里,我们用一个监听按钮的点击事件,来简单看看v-on的使用

下面的代码中,我们使用了v-on:click="counter++”

另外,我们可以将事件指向一个在methods中定义的函数

vue-基础语法和组件化开发

2.2. 参数问题

btnClick

btnClick(event) :!--2.在事件定义时, 写方法时省略了小括号, 但是方法本身是需要一个参数的, 这个时候, Vue会默认将浏览器生产的event事件对象作为参数传入到方法-->

btnClick(abc, event) -> $event : !--3.方法定义时, 我们需要event对象, 同时又需要其他参数-->

!-- 在调用方式, 如何手动的获取到浏览器参数的event对象: $event-->

当通过methods中定义方法,以供@click调用时,需要注意参数问题:
情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。
但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件

vue-基础语法和组件化开发

Event 本身包含适用于所有事件的属性和方法。

构造器:可以使用event()创建一个event对象

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。事件通常与函数结合使用,函数不会在事件发生前被执行!

2.3. 修饰符

stop

prevent

.enter

.once

.native

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

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

.stop - 调用 event.stopPropagation()。

.prevent - 调用 event.preventDefault()。

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

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

.once - 只触发一次回调。

vue-基础语法和组件化开发

三. 条件判断

3.1. v-if/v-else-if/v-else

v-if、v-else-if、v-else

这三个指令与JavaScript的条件语句if、else、else if类似。

Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件

简单的案例演示:

vue-基础语法和组件化开发

v-if的原理:

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

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

3.2. 登录小案例

用户再登录时,可以切换使用用户账号登录还是邮箱地址登录。
类似如下情景:

vue-基础语法和组件化开发

小问题:
如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
但是按道理讲,我们应该切换到另外一个input元素中了。
在另一个input元素中,我们并没有输入内容。
为什么会出现这个问题呢?

问题解答:
这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。
在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。

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

vue-基础语法和组件化开发

3.3. v-show

v-show和v-if区别

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

vue-基础语法和组件化开发

四. 循环遍历

4.1. 遍历数组

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

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

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

我们来看一个简单的案例:

如果在遍历的过程中不需要使用索引值

v-for="movie in movies"

依次从movies中取出movie,并且在元素的内容中,我们可以使用Mustache语法,来使用movie

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

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

其中的index就代表了取出的item在原数组的索引值。

vue-基础语法和组件化开发

    totalPrice() {       // 1.普通的for循环       // let totalPrice = 0       // for (let i = 0; i < this.books.length; i++) {       //   totalPrice += this.books[i].price * this.books[i].count       // }       // return totalPrice        // 2.for (let i in this.books)       // let totalPrice = 0       // for (let i in this.books) {       //   const book = this.books[i]       //   totalPrice += book.price * book.count       // }       //       // return totalPrice        // 3.for (let i of this.books)       // let totalPrice = 0       // for (let item of this.books) {       //   totalPrice += item.price * item.count       // }       // return totalPrice        return this.books.reduce(function (preValue, book) {         return preValue + book.price * book.count       }, 0)     } 

4.2. 遍历对象

value

value, key

value, key, index

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

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

vue-基础语法和组件化开发

4.3. 数组哪些方法是响应式的

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

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

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

这里我们借用React’s diff algorithm中的一张图来简单说明一下:

当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点

我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。

即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

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

Diff算法就可以正确的识别此节点

找到正确的位置区插入新的节点。

所以一句话,key的作用主要是为了高效的更新虚拟DOM。

vue-基础语法和组件化开发

vue-基础语法和组件化开发

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

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

push() 往最后添加元素 (可以添加多个元素)

pop() 删除数据中的最后一个元素

shift() 删除我们数组中的第一个元素

unshift() 在数组最前面添加元素 (可以添加多个元素)

splice() 作用<删除元素 / 插入元素/ 替换元素>

删除元素 splice(1,2), 第二个参数传入你要删除几个元素(如果没有传删除,就删除后面所有的元素)

插入元素splice(1,3,'m','n','u','x') 第二个参数表示我们要替换几个元素,后面是用于替换前面的元素

替换元素splice(1,0,'x','y','z') 第二个参数传入0 ,并且后面跟上要插入的元素

sort() 排序

reverse() 反转

vue-基础语法和组件化开发

注意: 通过索引值修改数组中的元素(不是响应式)

    // this.letters[0] = 'bbbbbb'; 

解决办法this.letters.splice(0, 1, 'bbbbbb')

   // set(要修改的对象, 索引值, 修改后的值)    // Vue.set(this.letters, 0, 'bbbbbb') 

4.3. 数组哪些方法是响应式的小案例 点击 那个那个添加样式

  • <!DOCTYPE html> <html lang="en"> <head>   <meta charset="UTF-8">   <title>Title</title>   <style>     .active {       color: red;     }   </style> </head> <body>  <div id="app">   <ul>     <li v-for="(item, index) in movies"         :class="{active: currentIndex === index}"         @click="liClick(index)">       {{index}}.{{item}}     </li>   </ul> </div>  <script src="../js/vue.js"></script> <script>   const app = new Vue({     el: '#app',     data: {       movies: ['海王', '海贼王', '加勒比海盗', '海尔兄弟'],       currentIndex: 0     },     methods: {       liClick(index) {         this.currentIndex = index}}}) </script> </body> </html> 

五. v-model的使用

默认情况下再给变量赋值都是字符串类型

5.1. v-model的基本使用

vue-基础语法和组件化开发

5.2 表单绑定v-model

v-model => v-bind:value v-on:input

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

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

vue-基础语法和组件化开发

案例的解析:

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

因为input中的v-model绑定了message,所以会实时将输入的内容传递给message,message发生改变。

当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。

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

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

vue-基础语法和组件化开发

5.3v-model原理

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

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

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

也就是说下面的代码:等同于下面的代码:

<input type="text" v-model="message"> 等同于 <input type="text" v-bind:value="message" v-on:input="message = $event.target.value"> 

vue-基础语法和组件化开发

5.4. v-model和radio/checkbox/select

当存在多个单选框时

vue-基础语法和组件化开发

v-model:checkbox

单个勾选框:

v-model即为布尔值。

此时input的value并不影响v-model的值

多个复选框:

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

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

vue-基础语法和组件化开发

vue-基础语法和组件化开发

v-model:select

单选:只能选中一个值。

v-model绑定的是一个值。

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

多选:可以选中多个值。

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

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

vue-基础语法和组件化开发

5.5. 修饰符

lazy:

默认情况下,v-model默认是在input事件中同步输入框的数据的。

也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。

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

number:

默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。

但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。

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

trim:

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

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

vue-基础语法和组件化开发

5.6值绑定

初看Vue官方值绑定的时候,我很疑惑:what the hell is that?

但是仔细阅读之后,发现很简单,就是动态的给value赋值而已:

我们前面的value中的值,可以回头去看一下,都是在定义input的时候直接给定的。
但是真实开发中,这些input的值可能是从网络获取或定义在data中的。
所以我们可以通过v-bind:value动态的给value绑定值。
这不就是v-bind吗?

这不就是v-bind在input中的应用吗?搞的我看了很久,搞不清他想讲什么。

这里不再给出对应的代码,因为会用v-bind,就会值绑定的应用了。

六. 组件化开发

6.1. 认识组件化

什么是组件化

人面对复杂问题的处理方式:

任何一个人处理信息的逻辑能力都是有限的

所以,当面对一个非常复杂的问题时,我们不太可能一次性搞定一大堆的内容。

但是,我们人有一种天生的能力,就是将问题进行拆解。

如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,你会发现大的问题也会迎刃而解。

组件化也是类似的思想:

如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。

但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

vue-基础语法和组件化开发

vue-基础语法和组件化开发

vue-基础语法和组件化开发

Vue组件化思想

组件化是Vue.js中的重要思想

它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。

任何的应用都会被抽象成一颗组件树。

vue-基础语法和组件化开发

组件化思想的应用:

有了组件化的思想,我们在之后的开发中就要充分的利用它。

尽可能的将页面拆分成一个个小的、可复用的组件。

这样让我们的代码更加方便组织和管理,并且扩展性也更强。

所以,组件是Vue开发中,非常重要的一个篇章,要认真学习。

6.2. 组件的基本使用

注册组件的基本步骤

组件的使用分成三个步骤:

创建组件构造器

注册组件

使用组件。

我们来看看通过代码如何注册组件

查看运行结果

和直接使用一个div看起来并没有什么区别。

但是我们可以设想,如果很多地方都要显示这样的信息,我们是不是就可以直接使用来完成呢?

vue-基础语法和组件化开发

注册组件步骤解析

这里的步骤都代表什么含义呢?

1.Vue.extend():

调用Vue.extend()创建的是一个组件构造器。

通常在创建组件构造器时,传入template代表我们自定义组件的模板。

该模板就是在使用到组件的地方,要显示的HTML代码。

事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。

2.Vue.component():

调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。

所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

3.组件必须挂载在某个Vue实例下,否则它不会生效。(见下页)

我们来看下面我使用了三次

而第三次其实并没有生效:

vue-基础语法和组件化开发

6.3. 全局组件和局部组件

当我们通过调用Vue.component()注册组件时,组件的注册是全局的

这意味着该组件可以在任意Vue示例下使用。

如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件

vue-基础语法和组件化开发

6.4. 父组件和子组件

在前面我们看到了组件树:

组件和组件之间存在层级关系

而其中一种非常重要的关系就是父子组件的关系

我们来看通过代码如何组成的这种层级关系:

父子组件错误用法:以子标签的形式在Vue实例中使用

因为当子组件注册到父组件的components时,Vue会编译好父组件的模块

该模板的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中的内容了)
是只能在父组件中被识别的。

类似这种用法,是会被浏览器忽略的。

vue-基础语法和组件化开发

6.5. 注册的语法糖

在上面注册组件的方式,可能会有些繁琐。

Vue为了简化这个过程,提供了注册的语法糖。

主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替。

语法糖注册全局组件和局部组件:

vue-基础语法和组件化开发

6.6.模板的分离写法

script

template

刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法。

如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。

Vue提供了两种方案来定义HTML模块内容:

使用<script>标签

使用<template>标签

vue-基础语法和组件化开发

6.7. 数据的存放

组件可以访问Vue实例数据吗?

组件是一个单独功能模块的封装:

这个模块有属于自己的HTML模板,也应该有属性自己的数据data。

组件中的数据是保存在哪里呢?顶层的Vue实例中吗?

我们先来测试一下,组件中能不能直接访问Vue实例中的data

vue-基础语法和组件化开发

组件数据的存放

组件对象也有一个data属性(也可以有methods等属性,下面我们有用到)

只是这个data属性必须是一个函数

而且这个函数返回一个对象,对象内部保存着数据

vue-基础语法和组件化开发

子组件不能直接访问父组件

子组件中有自己的data, 而且必须是一个函数.

为什么必须是一个函数.

为什么data在组件中必须是一个函数呢?

首先,如果不是一个函数,Vue直接就会报错。

其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

vue-基础语法和组件化开发

6.8. 父子组件的通信

在上一个小节中,我们提到了子组件是不能引用父组件或者Vue实例的数据的。

但是,在开发中,往往一些数据确实需要从上层传递到下层:

比如在一个页面中,我们从服务器请求到了很多的数据。

其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。

这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。

如何进行父子组件间的通信呢?Vue官方提到

通过props向子组件传递数据

通过事件向父组件发送消息

vue-基础语法和组件化开发

在下面的代码中,我直接将Vue实例当做父组件,并且其中包含子组件来简化代码。

真实的开发中,Vue实例和子组件的通信和父组件和子组件的通信过程是一样的。

父传子: props

在组件中,使用选项props来声明需要从父级接收到的数据。

props的值有两种方式:

方式一:字符串数组,数组中的字符串就是传递时的名称。

方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

我们先来看一个最简单的props传递:

vue-基础语法和组件化开发

props数据验证

在前面,我们的props选项是使用一个数组。

我们说过,除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。

验证都支持哪些数据类型呢?

String

Number

Boolean

Array

Object

Date

Function

Symbol

vue-基础语法和组件化开发

当我们有自定义构造函数时,验证也支持自定义的类型

vue-基础语法和组件化开发

子传父: $emit

props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。

我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成。

什么时候需要自定义事件呢?

当子组件需要向父组件传递数据时,就要用到自定义事件了。

我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。

自定义事件的流程:

在子组件中,通过$emit()来触发事件。

在父组件中,通过v-on来监听子组件事件。

我们来看一个简单的例子:

我们之前做过一个两个按钮+1和-1,点击后修改counter。

我们整个操作的过程还是在子组件中完成,但是之后的展示交给父组件。

这样,我们就需要将子组件中的counter,传给父组件的某个属性,比如total。

自定义事件代码

vue-基础语法和组件化开发

6.9. 项目

npm install 安装依赖node

npm run serve 启动项目

七.JavaScript 高阶函数使用

编程范式: 命令式编程/声明式编程 编程范式: 面向对象编程(第一公民:对象)/函数式编程(第一公民:函数) filter/map/reduce filter中的回调函数有一个要求: 必须返回一个boolean值 true: 当返回true时, 函数内部会自动将这次回调的n加入到新的数组中 false: 当返回false时, 函数内部会过滤掉这次的n const nums = [10, 20, 111, 222, 444, 40, 50]  let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n); console.log(total);  let total = nums.filter(function (n) {   return n < 100 }).map(function (n) {   return n * 2 }).reduce(function (prevValue, n) {   return prevValue + n }, 0) console.log(total);  1.filter函数的使用 // 10, 20, 40, 50 let newNums = nums.filter(function (n) {   return n < 100 })  console.log(newNums);   2.map函数的使用  20, 40, 80, 100 let new2Nums = newNums.map(function (n) { // 20   return n * 2 }) console.log(new2Nums);   3.reduce函数的使用  reduce作用对数组中所有的内容进行汇总 let total = new2Nums.reduce(function (preValue, n) {   return preValue + n }, 0) console.log(total);  第一次: preValue 0 n 20 第二次: preValue 20 n 40 第二次: preValue 60 n 80 第二次: preValue 140 n 100 240  1.需求: 取出所有小于100的数字 let newNums = [] for (let n of nums) {   if (n < 100) {     newNums.push(n)   } }  // 2.需求:将所有小于100的数字进行转化: 全部*2 let new2Nums = [] for (let n of newNums) {   new2Nums.push(n * 2) }  console.log(new2Nums);   // 3.需求:将所有new2Nums数字相加,得到最终的记过 let total = 0 for (let n of new2Nums) {   total += n }  console.log(total);