Vue 2.0 基础学习笔记

前言

接触 Vue 也有一段时间了,很多时候在项目里面会用,但是由于对整个 Vue 的了解比较片面,让我不得不一次又一次地含泪填坑。不过真是这样的经历,也让我对 Vue 有了很多新的认识。

为了深入地学习 Vue 2.0,就决定写一个系列的学习笔记,希望在记录自己走过的路的同时,也能和一起学的伙伴互相交流。所以,也希望看完博客的小伙伴,如果发现我的什么错误或者遗漏,也希望及时地提出来。

关于 Vue 2.0 的学习笔记是一个系列的集合,包括 Vue 基础学习、高级组件学习、插件开发和实际应用,所涵盖的知识点和技能点也是方方面面,本文主要针对 Vue 2.0 的常用方法进行了总结,不包括 Vue 是啥东西?怎么安装?这个 Vue 官网 已经说的很详细了,可以根据它的教程一步一步来。

放个 Vue 2.0 学习笔记其它部分的传送门(我会坚持都写完的 TAT):

好的,我们开始吧!

1. 生命周期

每个 Vue 实例在被创建之前都要经过一系列的初始化过程,在这个过程中,实例也会调用一些生命周期钩子 ,这就给我们提供了执行自定义逻辑的机会。

那么怎么使用这些钩子呢?我们先看一个 Vue 实例的生命周期图:

Vue 实例的生命周期图

如上图所示,Vue 的生命周期一共有CreateMountUpdate以及Destroy四个步骤。而 Vue.js 也提供了八个钩子函数给我们自定义逻辑:

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeDestroy
  • destroyed

从字面上来解释就分别是创建前后、挂载前后、更新前后以及销毁前后。

注意:Mount 比较简单的理解就是 Vue 上的el替代了 DOM 元素。

我们再通过一个例子来说明一下:

<template>
    <div id="demo1">{{data}}</div>
</template>

<script>
    export default {
        data() {
            return {
                name: 'demo1',
                a: '999',
                data: 'this is data'
            }
        },
        beforeCreate() {
            console.log('beforeCreate')
        },
        created() {
            console.log('created')
        },
        beforeMount() {
            console.log('beforeMount')
        },
        mounted() {
            console.log('mounted')
        },
        beforeUpdate() {
            console.log('beforeUpdate')
        },
        updated() {
            console.log('updated')
        },
        beforeDestroy() {
            console.log('beforeDestroy')
        },
        destroyed() {
            console.log('destroyed')
        },
        watch: {
            a: function (val, oldVal) {
              console.log(`new: ${val}, old: ${oldVal}`)
            }
        }
    }
</script>

我们打开控制台就会发现,初次加载时会触发CreateMount的生命周期钩子:

在控制台中修改 data 中的值,以及调用$destroy()方法,分别会触发UpdateDestroy的生命周期钩子:

另外值得一提的是,根据官网给出的描述:

“每个 Vue 实例都会代理其 data 对象里的所有属性。”

通俗一点说就是,data 对象是引用类型,其值是该对象的地址,所以你改变 data 中的值之后,Vue 实例中的值也会跟着改变,反过来也是同理。不过有一点在写 SPA 的时候可能不会注意到的是,把一个对象赋值给 Vue 实例以后,再给该对象增加属性,新属性并不会被原本的 Vue 实例所引用。例如:

// html
<div id="demo2"></div>

// js
const demoData = {
    name: 'demo2',
    a: '999',
    data: 'this is data'
}
const demo = new Vue({
    el: '#demo2',
    data: demoData
})

demoData.b = '998'

这样并不能把新属性添加到实例里面。

把话题撤回来,使用了$destroy()方法就会触发 Destroy 的生命周期钩子,会拆解监控,也就是解除双向绑定,值得变化不会再引起 DOM 的变化:

如上图所示,修改了 data 之后,DOM 上的值依旧没有发生变化。

2. 计算属性

计算属性被混入到 Vue 实例中,所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。

注意:不应该使用箭头函数来定义计算属性函数 (例如aDouble: () => this.a * 2)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。

先看 demo 的以下代码:

<template>
    <div id="demo3">
        <p>{{fullName}}</p>
        <p>{{getFullName()}}</p>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                firstName: 'Larry',
                lastName: 'Xiao'
            }
        },
        methods: {
            getFullName() {
                console.log('method exec')
                return `${this.firstName} ${this.lastName}`
            }
        },
        computed: {
            fullName: {
                get() {
                    return `${this.firstName} ${this.lastName}`
                },
                set(newVal) {
                    let names = newVal.split(' ')
                    this.firstName = names[0]
                    this.lastName = names[names.length-1]
                }
            }
        },
        watch: {
            a: function (val, oldVal) {
              console.log('watch exec')
              alert('firstName has changed!')
            }
        }
    }
</script>

可以看到的是,在 computed 中的fullName和 methods 中的getFullName()效果是一样的。根据文档上的说法,计算属性是使用计算缓存的,当计算属性的依赖项发生变化时,计算属性才会重新计算,其他时候都是直接返回缓存中的值,而 method 总是会执行函数。

另外,计算属性默认是 get 模式,同时也可以采用 set 模式。

因此,计算属性在大多数情况都更合适,当不需要缓存的时候用 method,需要缓存的时候用计算属性 computed,有时候需要在数据变化时来响应数据变化,就需要用到 watch 方法。

3. Class 绑定

在将v-bind用于 class 和 style 的时候,表达式的结果类型除了字符串外,还可以是对象是数组:

对象的绑定方式很简单,使用v-bind:class就行了。

需要注意的有:

  • v-bind:class可以和普通的 class 属性共存;
  • v-bind:class赋值的对象除了是 js 的字面量意外,也可以是 data 中所指向的对象,同时还能是 computed 计算属性中返回的对象。

关于数组绑定,可以把一个数组传递给v-bind:class,以应用一个class列表,同时也可以在数组中使用对象:v-bind:class="[{active:isActive},selectCss]"。当然同样的道理,也可以使用计算属性。

4. 内联样式绑定

内联样式的绑定和 class 的绑定几乎没有区别,同样也是可以绑定对象和数组:v-bind:style="{color:'red';fontSize:'30px'}",有一点要注意的是,css 的属性名除了用驼峰法,还可以用短横分割法命名:v-bind:style="{color:'blue','font-size':'30px',}"v-bind:style="{color:'blue',fontSize:'30px',}"的效果是一模一样的。当然,把v-bind:style绑定到一个样式对象上是个更好的做法。

数组的用法和 class 的一样,最后值得一提的是:当v-bind:style使用需要特定前缀的 css 属性时,如transform,会自动添加前缀。并且在 chrome 浏览器下,并没有加上-webkit-前缀。

5. 条件渲染

5.1 v-if

在 Vue 项目里面,一般在处理条件渲染的时候,都会使用v-if来处理,而更为强大的一点在于,还有v-elsev-else-if来处理多种条件下的渲染问题。

由于v-if只是一种标签里的指令,如果需要按条件渲染多个元素的时候,就需要用到<template></template>,把多个元素放在template里面,把v-if指令放到template上。

Vue 尝试尽可能高效的渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 更快之外还可以得到一些好处。就像这样,当允许用户在不同的登录方式之间切换:

<template v-if="loginType === 'username'"> 
    <label>Username</label> 
    <input placeholder="Enter your username"> 
</template> 
<template v-else> 
    <label>Email</label> 
    <input placeholder="Enter your email address"> 
</template>

在控制台切换loginType,会显示不同的 label 和 plaaceholder,但是在切换的时候,input 的内容并不会被删除,两个模版因为使用了相同的元素,因此<input>会被复用,仅仅只是替换了 placeholder。当然,Vue 也提供了一种方式让你自己决定是否要复用元素,所要做的就是加一个 key 属性。

5.2 v-show

另一个根据条件渲染元素的指令叫v-show,和v-if的区别在于v-show做的仅仅只是切换元素的 css 中的display属性。另外v-show也不支持 template 语法。

5.3 v-if 和 v-show 的区别:

  • v-if是真实的条件渲染,因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件。
  • v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做,在条件第一次变为真时才开始局部编译(编译会被缓存起来)。

相比之下,v-show简单得多:元素始终被编译并保留,只是简单地基于 CSS 切换。一般来说,v-if有更高的切换消耗,而v-show有更高的初始渲染消耗。因此,如果需要频繁切换使用v-show较好,如果在运行时条件不大可能改变则使用v-if较好。

6. 列表渲染

在 Vue 的列表渲染中,主要使用v-for="item in items"的指令来进行元素渲染。和条件渲染一样,当有多个元素需要被渲染的时候,也可以使用<template v-for=""></template>来渲染。

v-for指令除了可以渲染数组以外,也能渲染对象以及整数的迭代:

  • 在渲染数组时,v-for还支持可选的第二个参数为当前项的索引,即v-for="(item,index) in intems"
  • 而在渲染对象时,v-for支持第二个可选参数作为键名,第三个参数作为索引,v-for="(value,key,index) in items"
  • 进行整数迭代时:<span v-for="x in 15">{{x}}</span>

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,我们需要为每项提供一个唯一的 key 属性。理想的 key 值是每项都有唯一 id,它的工作方式类似于一个属性,所以你需要用 v-bind 来绑定动态值:

<div v-for="item in items" :key="item.id">
    <!-- :key 是对于 v-bind 的一种简写方式 -->
</div>

除了这些,Vue 还包含一组观察数组的变异方法,它们也会触发视图的更新:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

7. 事件处理器

事件处理器可以使用v-on指令或者缩写@来完成事件绑定,比如我们要绑定一个 click 事件:

<template>
    <button v-on:click="add">add</button>
    <span></span>
</template>
<script>
    data() {
        return {
            count: 0
        }
    }
    methods: {
        add() {
            this.count ++
        }
    }
</script>

有时候需要在v-on绑定的事件中处理原生 DOM 的事件,则可以使用$event将它传入方法:

<template>
    <button v-on:click="warn('Form cannot be submitted yet.', $event)">Submit</button>
</template>
<script>
    data() {
        return {
        }
    }
    methods: {
        warn (message, event) { 
            if (event) {
                event.preventDefault() 
            }
            alert(message) 
        }
    }
</script>

之前提到的,我们需要在方法中除了原生 DOM 事件,主要也是为了阻止冒泡方法,为了让我们可以再 method 中专注于业务逻辑,Vue 提供了一些事件修饰符

  • stop:阻止事件冒泡;
  • prevent:事件触发不再重载页面;
  • capture:添加事件监听器时使用事件捕获模式;
  • self:只有该事件是自己本身(而不包括子元素)时才会触发回调;
  • once:只触发一次。

还有一点要注意的是,事件修饰符是可以串联使用的,比如v-on:click.stop.prevent="click"

在监听键盘事件时,还需要监听常见的键值,Vue 允许v-on在监听键盘事件时,添加特殊的键盘修饰符,基本的键盘修饰符有:

  • .enter
  • .tab
  • .delete
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

还有组合按键的修饰符:

  • .ctrl
  • .shift
  • . alt
  • .meta(window 系统下是 window 键,mac 下是 command 键)

8. 表单控件绑定

所谓的表单控件其实就是使用v-model指令放在<input><textarea><select>这些控件上实现双向绑定。如果是多选,v-model绑定的对象一定要是个数组,同时可以通过v-bind来为 “表单控件” 设置 value 值。

并且,还可以在v-model中使用修饰符来进行一些常用操作:

  • .lazy:在默认情况下,v-model在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在事件中同步:
<input v-model.lazy="msg">
  • .number:如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给v-model来处理输入值:
<input v-model.number="age" type="number">
  • .trim:如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到v-model上过滤输入:
<input v-model.trim="msg">

总结

本文大概地过了一遍 Vue 2.0 的基础知识,也可能还有很多方面不够详尽,希望大佬可以多提建议。还有一点比较重要的就是,学习 Vue 2.0 的话,我个人还是建议去 Vue 官网 跟着一步一步地敲代码,博客只是一个总结概括的东西,真正理解还得自己实践。

当然,也希望这些总结可以对我自己,以及对刚接触 Vue 2.0 的小伙伴有些帮助吧!

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 4,739评论 0 29
  • 1.安装 可以简单地在页面引入Vue.js作为独立版本,Vue即被注册为全局变量,可以在页面使用了。 如果希望搭建...
    Awey阅读 10,501评论 4 129
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 1,827评论 0 6
  • 下载安装搭建环境 可以选npm安装,或者简单下载一个开发版的vue.js文件 浏览器打开加载有vue的文档时,控制...
    冥冥2017阅读 5,652评论 0 42
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 131,792评论 18 138
  • 文/愚木 我给你讲一个故事吧? 在清晨,在日暮! 在我们穷途末路以后。 讲一个没有结局的故事: 在很久很久以前……...
    愚木的简书阅读 270评论 1 4
  • 谁拿曾经,旧了新年 谁用烈酒,醉了流年 毕业了。应该说是又毕业了。却发现这次毕业好像不太一样,因为再不会有下一所学...
    铖丶阅读 289评论 0 0
  • 1.女生喜欢有钱的男人,是因为他们代表背后的品质上进,积极 2.有钱人见多识广(带女生进出高档餐厅,女生不适应的压...
    CNBLUEone阅读 1,212评论 0 1