《Vue.js 实战》基础篇(上)

本章内容:认识 Vue.js、数据绑定、计算属性、内置指令

一、初始 Vue.js

1.1 Vue.js 是什么

简单小巧的核心,渐进式技术栈,足以应付任何规模的应用。
简单小巧 指Vue.js 压缩后大小仅 17KB
所谓渐进式(Progressive)就是你可以一步一步、有阶段性地来使用 Vue.js

Vue.js 提供了现代 Web 开发中常见的高级功能,比如:

  • 解耦视图与数据
  • 可复用的组件
  • 前端路由
  • 状态管理
  • 虚拟 DOM(Virtual DOM)
1.1.1 MVVM 模式

Vue.js使用 MVVM (Model-View-ViewModel)模式。MVVM 模式是由经典的软件架构MVC 衍生而来的。当 View(视图层)变化时,会自动更新到 ViewModel(视图模型),反之亦然

《Vue.js 实战》基础篇(上)_第1张图片
MVVM 关系

1.1.2、Vue.js 有什么不同

与传统开发模式相比,Vue.js 通过 MVVM 的模式拆分为 视图数据 两部分,并将其分离,因此,你只需要关系数据即可,DOM的 事情 Vue 会自动帮你搞定。

1.2、如何使用 Vue.js

1.2.1、传统的前端开发模式

前些年称之为“万金油” 的一套技术栈:

jQuery + RequireJS(SeaJS) + artTemplate(doT) + Gullp(Grunt)

这套技术栈 以 jQuery 为核心,RequireJS 或 SeaJS 进行模块开发;加上轻量级的前端模板artTemplate 或 doT;最后使用自动构建工具(如 Gulp)压缩代码

1.2.2、Vue.js 的开发模式

Vue.js 是一个渐进式框架,根据项目需求的不同,你可以选择从不同的维度来使用它。

  • 如果只是想体验 Vue.js 或 开发简单的 HTML5页面 或 小应用,可以直接通过

    在输入框输入的内容会实时展示在 页面的 h1 标签内,虽然这是一段简单的代码,却展示了 Vue.js 最核心的功能:数据的双向绑定

    2.1、Vue 实例 与 数据绑定

    2.1.1、实例 与 数据

    Vue.js 应用的创建很简单,通过 构造函数 Vue 就可以 创建一个 Vue 实例,并启动 Vue 应用。

    const app = new Vue({
      // options
    })
    

    app 就代表了这个 Vue 实例

    实例选项

    首先,必不可少的一个选项就是 el。el 用于指定一个页面中已经存在的 DOM
    元素来挂载 Vue 实例,他可以是 HTMLElement,也可以是 CSS 选择器。

    const app1 = new Vue({
      el: document.getElementById('app')
    })
    
    const app2 = new Vue({
      el: '#app'
    })
    

    挂载成功后,我们可以通过 app.$el 来访问该元素

    data 选项,可以声明应用中需要双向绑定的数据,建议所有会用到的数据都预先在 data 内声明,这样不至于将数据散落在业务逻辑中,难以维护。
    Vue 实例本身也代理了 data 对象里的所有属性,所以可以这样访问:

    var app = new Vue({
      el: '#app',
      data: {
        a: 1
      }
    })
    
    console.log(app.a) // 1
    

    处理显式地声明数据外,也可以指定一个已有的变量,并且他们之间默认建立了双向数据绑定,当修改其中任意一个时,另一个也会一起改变。

    2.1.2、生命周期

    每个 Vue 实例创建时,都会经历一系列的初始化过程,同时也会调用相应的生命周期钩子,我们可以利用这些钩子,在合适的时机执行我们的业务逻辑。
    比较常用的有:

    • created:实例创建完成后调用,此阶段完成了数据的观测等,但尚未挂载,$el 还不可用。需要初始化处理一些数据时比较有用
    • mounted:el 挂载到实例上后调用,一般我们的第一个业务逻辑在这里开始
    • beforeDestroy:实例销毁之前调用。主要解绑一些使用 addEventListener 监听的事件等。
      详细的声明周期函数,会在后面章节讲解
      这些钩子 与 eldata 类似,也是作为选项写入 Vue 实例内,并且 钩子的 this 指向的是调用它的 Vue 实例:
    var app = new Vue({
      el: '#app',
      data: {
        a: 2
      },
      created: function() {
        console.log(this.a) // 2
      },
      mouted: function() {
        console.log(this.$el) // 
    } })
    2.1.3、差值与表达式

    使用 双大括号(Mustache 语法)“{{}}” 是最基本的文本插值方法,它会自动将我们双向绑定的数据实时显示出来。

    
      
      

    {{ book }}

    如果有时候想要输出 HTML,而不是将数据解释后的存文本,可以使用 v-html

    
      
      

    这里要注意,如果将用户产生的内容 使用 v-html 输出后,有可能会导致 XSS 攻击,所以要在服务端对用户提交的内容进行处理,一般可将 尖括号 "<>" 转义


    如果想显示 {{}} 标签而不进行替换,可以使用 v-pre,即可跳过这个元素和它的子元素的编译过程。

     {{ 这里的内容不会被编译 }} 
    

    {{}} 中,处理简单的绑定属性外,还可以使用 JavaScript 表单是进行简单的运算、三元运算等,例如:

    {{num / 10}} {{ isOK ? '确定' : '取消' }} {{ text.split(',').reverse().join(',') }}

    Vue.js 只支持单个表达式,不支持语句和流程控制。另外,在表达式中,不能使用用户自定义的全局变量,只能使用 Vue 白名单内的全局变量,例如 Math 和 Date

    2.1.4、过滤器

    Vue.js 支持在 {{}} 插值的尾部添加一个 管道符 “ | ” 来对数据进行过滤,经曾用于格式化文本,比如字母全部大写,货币千位使用逗号分割等。过滤的规则是自定义的,通过给 Vue 实例添加 filters 来实现
    时间案例

    
      
      
    {{ date | formatDate}}

    过滤器也可以串联,而且可以接收参数

    
    {{ message | filterA | filterB }}
    
    
    {{ message | filter('arg1', 'arg2') }}
    

    这里的 arg1 和 arg2 将分别传给过滤器的第二个 和 第三个参数,因为第一个是数据本身。

    2.2、指令

    指令(Directives)是 Vue.js 模板中最常用的 一项功能,它带有前缀的 v-,Vue,js内置了很多指令,后面会详细讲到,在此之前,你需要先知道 v-bindv-on

    v-bind 的基本用途是动态更新 HTML 元素上的属性,比如 id、class 等
    例如下面示例:

    
      
      
    
      
      
    
    

    v-on,用来绑定事件监听,这样我们就可以实现一些交互

    
      
      

    The End of the F***ing World

    表达式可以是一个方法名,这些方法都写在 Vue 实例的 methods 属性内,并且是函数的形式,函数内的this 指向的是当前 Vue 实例本身,因此可以直接使用 this.xxx 的形式来访问或修改数据

    表达式除了方法名,也可以直接是一个内联语句。

      

    The End of the F***ing World

    如果绑定的事件要处理复杂的业务逻辑,建议还是在 methods 里声明一个方法,这样可读性更强也好维护。

    Vue.js 将 methods 里的方法也代理了,所以也可以像 访问 Vue 数据那样来调用方法。在外部 也可以通过 “实例.方法名” 调用内部的方法

    2.3、语法糖

    语法糖是指在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发。

    Vue.js 的 v-bind 和 v-on 指令都提供了语法糖,

    v-bind,可以省略 v-bind,直接写一个冒号 “:”

     连接 
    
    
    

    v-on 可以直接用 “@” 来缩写

    
    

    三、计算属性

    3.1、什么是计算属性

    在模板中双向绑定一些数据或表达式,如果过长,或逻辑更为复杂时,就会变得臃肿甚至难以阅读和维护,比如:

     {{ text.split(',').reverse().join(',') }}
    

    当遇到复杂的逻辑是应该使用 计算属性。

    
      
      
    {{ reversedText}}

    3.2、计算属性用法

    计算属性只要其中任意数据变化,计算属性就会重新执行,视图也会更新。

    
      
      
    总价:{{ prices }}

    如上 当 package 中的商品有任何变化时,计算属性 prices 就会自动更新

    每一个计算属性都包含一个 getter 和 一个 setter在你需要时,也可以提供一个 setter 函数,当手动修改计算属性的值就像修改一个普通数据那样时,就会触发 setter 函数,执行一些自定义操作。

    
      
      
    {{ fullName }}

    绝大多数情况下,我们只会用默认的 getter 方法来读取一个计算属性,在业务中很少用到 setter,所以在声明一个计算属性时,可以直接使用 默认的写法,不必将 getter 和 setter 都声明。

    计算属性还有两个很实用的小技巧容易被忽略:

    • 一是计算属性可以依赖其他计算属性;
    • 而是计算属性不仅可以依赖当前 Vue 实例的数据,还可以依赖其他实例的数据。

    3.3、计算属性缓存

    调用 methods 里的方法也可以 与 计算属性起到同样的作用。
    本小节的第一个例子,使用 methods改写:

    
      
      
    {{ reversedText() }}

    使用方法还可以接受参数,使用起来更灵活,那么为什么还需要计算属性呢?原因就是 计算属性是基于它的依赖缓存的。一个计算属性所依赖的数据发生变化时,它才会重新取值。所以 text 只要不改变,计算属性也就不更新。
    使用 计算属性 还是 methods 取决于你是否需要缓存,当遍历大数组和做大量计算时,应该使用计算属性,除非你不希望得到缓存。

    四、v-bind 及 class 与 style 绑定

    4.1、了解 v-bind 指令

    前面已经介绍了 v-bind 指令的基本用法及语法糖,它的主要用处是动态更新 HTML 元素上的属性。在数据绑定中,最常见的两个需求就是 元素的样式名称 class 和 内联样式 style 的动态绑定

    4.2、绑定 class 的几种方式

    4.2.1、对象语法

    给 v-bind:class 设置 一个对象,可以动态地切换 class
    例如

    
      
      

    对象中也可以传入多个属性,来动态切换 class。:class 与 普通 class 共存

    
      
      

    :class 内的表达式每项为真时,对应的类名就会加载。

    当 :class 的表达式过长 或 逻辑复杂时,还可以绑定一个计算属性,这是一种很友好和常见的用法,一般当条件多于两个时,都可以使用 data 或 computed。
    例如使用 计算属性:

    
      
      

    除了计算属性,你也可以直接绑定一个 Object 类型的数据,或者使用 雷士计算属性的 methods

    4.2.2、数组语法

    当需要应用多个 class 时,可以使用数组语法。

    
      
      

    也可以在数组中使用 三元表达式。

      

    当 class 有多个条件是,这样写比较烦琐,可以在数组语法中使用对象语法:

    
      
      

    与对象语法一样,也可以使用 data、computed、methods 三种方法。

    4.2.3、在组件上使用

    如果直接在 自定义组件上使用 class 或 :class,样式规则会直接应用到这个组件的根元素上,例如声明一个简单的组件:

    
      
      

    最终组件渲染的结果为:

    some text

    4.3、绑定内联样式

    使用 v-bind:style(:style) 可以给元素绑定内联样式,方法与 :class 类似,也有对象语法和数组语法,看起来很像直接在元素上写 CSS:

    
      
      
    The End of the F***ing World

    大多数情况下,直接写一长串的样式不便于阅读和维护,所以一般 写在 data 或 computed 里。

    
      
      
    The End of the F***ing World

    在实际业务中,:style 的数组语法并不常用,因为往往可以写在一个对象里面;而较为常用的应当时计算属性。
    在使用 :style 时, Vue.js 会自动给特殊的 CSS 属性 名称添加前缀(weikit、ms...)。

    五、内置指令

    5.1、基本指令

    5.1.1、v-cloak

    v-cloak 不需要表达式,它会在 Vue 实例结束编译是从绑定的 HTML 元素上移除,经常和 CSS 的 display: none; 配合使用。

    
      
    
    
      
      
    {{ message }}

    在一般情况下,v-cloak 是一个解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用。

    5.1.2、v-once

    v-once 也是一个不需要表达式的指令,作用是定义它的元素或组件只渲染一次,包括元素或组件的所有子节点。首次渲染后,不再随数据的变化重新渲染,将被视为静态内容。

    
      
      
    {{ message }}
    {{ message }}
    {{ message }}
    《Vue.js 实战》基础篇(上)_第2张图片
    渲染结果

    5.2、条件渲染指令

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

    与 JavaScript 的条件语句 if、else、else if 类似,Vue.js 的条件指令可以根据表达式的值在 DOM 中渲染或销毁元素/组件,例如:

    
      
      

    当 status 为1时显示 该行

    当 status 为2时显示 该行

    否则显示该行

    v-else-if 要紧跟 v-if, v-else 要跟紧 v-else-if 或 v-if
    表达式的值为真时,当前元素/组件及所有子节点被渲染,为假时被移除。

    如果一次判断多个元素,可以在 Vue.js 内置的