01. 什么是 Vue

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架,是当下很火的一个 JavaScript MVVM 库,是以 数据驱动和组件化 的思想构建的。

MVVM 模式简述

下图不仅概括了 MVVM 模式 (Model-View-ViewModel),还描述了在 Vue.js 中 ViewModel 是如何和 View 以及 Model 进行交互的。

ViewModel 是 Vue.js 的核心,它是一个 Vue 实例。Vue 实例是作用于某一个 HTML 元素上的,这个元素可以是 HTML 的 body 元素,也可以是指定了 id 的某个元素。

当创建了 ViewModel 后,双向绑定是如何达成的呢?

首先,我们将上图中的 DOM ListenersData Bindings 看作两个工具,它们是实现双向绑定的关键。

  • 从 View 侧看,ViewModel 中的 DOM Listeners 工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;
  • 从 Model 侧看,当我们更新 Model 中的数据时,Data Bindings 工具会帮我们更新页面中的 DOM 元素。

库和框架的区别

在这里我们需要稍微注意一下前端 库(Library)框架(Framework) 的区别,它们的本质都是某人编写的,用于解决常见问题的 可复用代码 的集合。

比如,你有一个处理字符串的程序,你为了保持代码的 DRY (Don't Repeat Yourself),你编写了如下可复用的功能代码:

function getWords(str) {
const words = str.split(' ');
return words;
}
function createSentence(words) {
const sentence = words.join(' ');
return sentence;
}

恭喜你,你创建了一个 JavaScript 库!

如果我们用 「构建房子」 来类比 「构建应用」 的话,那么 使用库 就像是 去宜家购物 一样,我已经有了一个家,现在我需要挑选自己喜欢的一些家具,以达到我自己满意的状态,这一切 都在我的控制范围之内;而 使用框架 就会像是已经有了一个 清装房,在已经规划好的蓝图和选择之中,我们的一些想法会显得十分地有限。

Vue.js 本身只是一个 JavaScript 库,包括 React 也一样,只不过平时我们所说的 Vue 框架,是指包含 Router/ Vuex 等一系列组件之后融合的 一整套解决方案

更加详细的解释如下:

  • 「库」 是一个封装好的特定的集合,提供给开发者使用,而且是特定于某一方面的集合(方法和函数),库没有控制权,控制权完全在于使用者本身;
  • 「框架」 顾名思义是一套架构,会基于自身的特点向用户提供一套比较完整的解决方案,如果使用者选定了一套框架,那么就需要根据框架本身做出一定的适应。

02. 为什么使用 Vue?

说实话,我个人非常喜欢 Vue。在我大学刚尝试学习 HTML + CSS + JavaScript 和 Bootstrap 融合之后,我就接触了 Vue,它对我来说这样的「前端小白」来说,几乎没有什么开发的门槛,很平滑地就得以过渡到 Vue 的使用中去。

典型的 .vue 文件可以简单成如下的样子:(vue-tutorial/typical-case.html)

<template>
<!-- HTML 代码 -->
</template> <script>
// JavaScript 代码
</script> <style>
/* css 代码 */
</style>

另外我也非常喜欢尤大大本人,大家可以去看一看 Honeypot 记录的关于 Vue 的 纪录片 (趁着写文的间隙我又看了一遍),当然如果英文有些吃力也可以围观一下在 B 站上的 带中文字幕的版本

Vue 从一开始的定位就是尽可能的降低前端开发的门槛,让更多的人能够更快地上手开发。———— 尤雨溪

理由一:易上手、学习曲线平滑

就像上面的典型 .vue 文件的展示一样,在 Vue 中,一切都很自然,例如我们使用 Vue 来构建我们的 Hello World 程序:(vue-tutorial/hello-vue.html)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Vue!</title>
</head>
<body>
<div id="app">
{{ message }}
</div> <!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 创建一个 Vue 实例或者说是 VieModel 实例
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</body>
</html>

可以看到几乎没有多余的部分,只是在创建 Vue 实例时,把 idapp 的对象 (此处为一个 div) 绑定到了 Vue 实例中而已。

理由二:文档友好

由于 Vue 是国人编写的,所以在官网中有完整的中文文档可供开发者参考,并且借由尤大大出色的文笔,非常地清晰易懂,相信看过的朋友会和我有一样的感受:

官方文档的地址可戳 这里

理由三:MVVM 天然的双向绑定

Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 JavaScript 库,这就让我们能够专注于 View 层的开发,这种轻量级的框架让前端开发更加高效、便捷。

例如,我们使用 v-model 来简单改造一下我们的 hello-vue.html 文件让它编程一个简单的双向绑定示例:(vue-tutorial/v-model-demo.html)

<div id="app">
<p>{{ message }}</p>
<input type="text" v-model="message" />
</div>

message 绑定到文本框,当更改文本框的值的时候, <p>{{ message }}</p> 中的内容也会被更新:

反过来如果我们更改 message 的值的话,文本框的值也会被更新,我们可以在控制台中尝试一下:

千万不要把框架能力看得比你解决问题的能力还重要

这里是借鉴了 知乎中的一个讨论,不论是使用 React 还是 Vue,我们最终还是要以 解决实际的问题 为出发点。引用一下尤大大在 知乎-Vue 和 React 的优点分别是什么? 上的回答部分截取:

说了这么多,无非是希望大家能停下来想想所谓的 ”A 技术比 B 技术牛逼“ 背后到底是在争些什么,我们使用这些技术的初衷又是什么。很多时候你说这方面,他说那方面,鸡同鸭讲,即使说到一起去,也往往缺乏对等的信息量或者基础共识,只是各自表达主观看法,最后变成两个阵营各自抱团取暖... 说到底,就算你证明了 A 比 B 牛逼,也不意味着你或者你的项目就牛逼了... 比起争这个,不如多想想怎么让自己变得更牛逼吧。—————— 尤雨溪

03. Vue 常用指令

上面我们已经实际体验了一个 Vue 的指令 v-model 了,在 Vue 中,指令都带有 v- 前缀,以表示它们是 Vue 提供的特殊的 attribute,它们会在渲染 DOM 时进行特殊的响应式行为。

Vue 内置了一些常用的指令,接下来我们将依次来介绍:

  • v-ifv-else 条件渲染指令;
  • v-show 条件展示指令;
  • v-for 列表渲染指令
  • v-bind 条件绑定指令;
  • v-on 事件处理指令;

大部分照搬的官方教程,写得非常具有参考性,感兴趣的朋友可以直接略过下面部分去参考 官方文档

v-if 和 v-else 条件渲染指令

v-if 指令

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。例如:(vue-tutorial/v-if-demo)

<p v-if="seen">现在你看到我了!</p>
var app = new Vue({
el: '#app',
data: {
seen: true
}
})

页面会正确的显示「现在你看到我了!」这几个字。

v-else 指令

你也可以使用 v-else 来添加一个 "else 块" 来表达条件不满足时应该渲染的模块:

<p v-if="seen">现在你看到我了!</p>
<p v-else>Oh no!</p>
var app = new Vue({
el: '#app',
data: {
seen: false
}
})

此时条件 seen 不满足,页面就会显示「Oh no!」的字样。

v-else-if 指令

这是 2.1.0 版本新增的指令,充当 v-if 的 "else-if 块",可以用来连续判断条件:

<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>

类似于 v-elsev-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

v-show 条件展示指令

另一个用于根据条件展示元素的选项是 v-show 指令。用法大致一样:

<h1 v-show="ok">Hello!</h1>

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display (条件不满足则把元素 display 属性设置为 none),而 v-if 则在条件不满足时直接不渲染出对象。

v-if 与 v-show

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是 惰性 的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

v-for 列表渲染指令

我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。

<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})

结果:

  • Foo
  • Bar

注意:永远不要把 v-if 和 v-for 同时用在同一个元素上。

因为当 Vue 处理指令时,v-forv-if 拥有更高的优先级,所以会导致错误,详细的技术细节可以 戳这里

v-bind 条件绑定指令

我们可以传给 v-bind:class 一个对象,以动态地切换 class:(也可以用缩写 : 来替代 v-bind 指令)

<div v-bind:class="{ active: isActive }"></div>

上面的语法表示 active 这个 class 存在与否将取决于数据属性 isActivetruthiness

你可以在对象中传入更多属性来动态切换多个 class。此外,v-bind:class 指令也可以与普通的 class 属性共存。当有如下模板:

<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>

和如下 data:

data: {
isActive: true,
hasError: false
}

结果渲染为:

<div class="static active"></div>

isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"

v-on 事件处理指令

可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。(也可以用缩写 @ 来替代 v-on 指令)

示例:

<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})

结果:

v-on 的事件修饰符

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 -->
<form v-on:submit.prevent></form> <!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div> <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

另外事件处理还可以支持 按键码 (某一个键按下)系统修饰符 (键盘鼠标按下),可以参看 官方教程

04. Todo-List 示例

上面我们了解了一些基本的指令了,接下来我们实际动动手,来搭建一个简单的 TodoList demo 小程序。

第一步:明确需求

TodoList 想必大家都很熟悉,使用来记录我们接下来要做的一些事情的程序,最基本的功能有增加和删除:

很简单,可以看出我们只需要一个输入框 (用来记录将要保存的数据),一个按钮 (用来添加数据),和一个集合 (用来保存数据) 就差不多可以了,上手!

第二步:创建好需要的 data

先来创建好我们需要的数据 data:

data: {
todos: [{
id: nextTodoId++,
text: '写代码'
},
{
id: nextTodoId++,
text: '还是写代码'
}
],
newTodoText: ""
}

这里多定义了 id 属性是为了方便我们的删除操作。

第三步:创建好对应的 HTML

没有任何布局,就直接定义好我们所需要的组件就好了:

<input type="text" v-model="newTodoText" />
<button @click="addItem">添加</button>
<ul>
<li v-for="item in todos">
<span>{{ item.text }}</span>
<span><button @click="removeItem(item.id)">del</button></span>
</li>
</ul>

没有任何的特别,只是里面包含了两个我们 未定义 的方法:addItemremoveItem 而已。

第三步:定义并实现方法

Vue 中的方法需要定义在 Vue 实例的 methods 关键字下面:

methods: {
addItem(key) {
this.todos.push({
id: nextTodoId,
text: this.newTodoText
})
this.newTodoText = ""
},
removeItem(id) {
this.todos = this.todos.filter(todo => {
return todo.id !== id
})
}
}

这里数组的更新需要用到 push,另外删除时我们使用了一个 lambda 表达式来完成,删除时传入了一个要删除元素的 id,然后从数组中挑选出所有 不等于 这个 id 的元素重新赋值给原数组,这样就相当于是删除了元素了。

本文涉及的所有代码都上传到了【More Than Java】项目中。(地址下方)

更好的参考

上面的代码仅仅是简单实现,更好的参考可以查看 Vue 官方实现的一个更加具有参考性的例子:https://codesandbox.io/s/o29j95wx9

参考资料

  1. Vue【官方文档】 - https://cn.vuejs.org/v2/guide/
  2. 【译】框架与库的差异 - https://juejin.im/post/5c5fe3e751882561dd7b4e9b
  3. Vue.js——60分钟快速入门 - https://www.cnblogs.com/keepfool/p/5619070.html
  • 本文已收录至我的 Github 程序员成长系列 【More Than Java】,学习,不止 Code,欢迎 star:https://github.com/wmyskxz/MoreThanJava
  • 个人公众号 :wmyskxz,个人独立域名博客:wmyskxz.com,坚持原创输出,下方扫码关注,2020,与您共同成长!

非常感谢各位人才能 看到这里,如果觉得本篇文章写得不错,觉得 「我没有三颗心脏」有点东西 的话,求点赞,求关注,求分享,求留言!

创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

懂一点前端—Vue快速入门的更多相关文章

  1. 懂一点Python系列——快速入门

    本文面相有 一定编程基础 的朋友学习,所以略过了 环境安装.IDE 搭建 等一系列简单繁琐的事情. 一.Python 简介 Python 英文原意为 "蟒蛇",直到 1989 年荷 ...

  2. vue 快速入门 系列 —— vue 的基础应用(上)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(上) Tip: vue 的基础应用分上下两篇,上篇是基础,下篇是应用. 在初步认识 vue一文中,我们已经写了一个 vue 的 hello- ...

  3. vue 快速入门 系列 —— vue-cli 下

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 下 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

  4. vue 快速入门 系列 —— 初步认识 vue

    其他章节请看: vue 快速入门 系列 初步认识 vue vue 是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架. 所谓渐进式,就是你可以一步一步.有阶段 ...

  5. vue 快速入门 系列 —— vue loader 上

    其他章节请看: vue 快速入门 系列 vue loader 上 通过前面"webpack 系列"的学习,我们知道如何用 webpack 实现一个不成熟的脚手架,比如提供开发环境和 ...

  6. vue 快速入门 系列 —— vue loader 下

    其他章节请看: vue 快速入门 系列 vue loader 下 CSS Modules CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统.vue-loader 提供了与 CSS ...

  7. vue 快速入门 系列 —— vue-router

    其他章节请看: vue 快速入门 系列 Vue Router Vue Router 是 Vue.js 官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌. 什么是路由 ...

  8. vue 快速入门 系列 —— 使用 vue-cli 3 搭建一个项目(上)

    其他章节请看: vue 快速入门 系列 使用 vue-cli 3 搭建一个项目(上) 前面我们已经学习了一个成熟的脚手架(vue-cli),笔者希望通过这个脚手架快速搭建系统(或项目).而展开搭建最好 ...

  9. vue 快速入门 系列 —— 使用 vue-cli 3 搭建一个项目(下)

    其他章节请看: vue 快速入门 系列 使用 vue-cli 3 搭建一个项目(下) 上篇 我们已经成功引入 element-ui.axios.mock.iconfont.nprogress,本篇继续 ...

  10. Vue快速入门(一)

    目录 Vue快速入门(一) 介绍 Vue.js 是什么 M-V-VM思想 安装 CDN引入 下载到本地 快速使用 双向数据绑定测试 模板语法 插值语法 指令 文本指令 v-html:让HTML渲染成页 ...

随机推荐

  1. 48.DRF版本控制

    版本控制 版本控制是前后端分离开发一个非常重要的内容,比如说我们重要服务修改.升级等发生版本变化v1.v2.v3等,但是版本发生了变化比如 v1升级到了v2版本,v1版本还有业务在继续使用,相当于同时 ...

  2. python 中异常类型总结

    异常类型: 异常名称 描述BaseException             所有异常的基类SystemExit                   解释器请求退出KeyboardInterrupt  ...

  3. useEffect与useLayoutEffect

    useEffect与useLayoutEffect useEffect与useLayoutEffect可以统称为Effect Hook,Effect Hook可以在函数组件中执行副作用操作,副作用是指 ...

  4. Swoole从入门到入土(5)——TCP服务器[异步任务]

    无论对于B/S还是C/S,程序再怎么变,唯一不变的是用户不想等太久的躁动心情.所以服务端对于客户的请求,能有多快就多快.如果服务端需要执行很耗时的操作,就需要异步任务处理机制,保证当前的响应速度不受影 ...

  5. org.apache.http.client.ClientProtocolException: URI does not specify a valid host name:localhost:xxx

    今天部署应用的时候遇到的,总结一下我知道的有2个原因: 1.地址前要加http://  这就是标题报错的原因,他用的是localhost:xxx 2.地址本身拼错了也会报这个,例如地址:http:// ...

  6. 【.Net Core】.Net Core 源码分析与深入理解 - 入口 Program.cs (一)

    研究原因:学习 .Net Core 两年有余,实际项目也使用了一年半,自己的技术已经到了瓶颈,需要有一个突破,我觉得首先研究架构师的设计思想,其次分析一下.Net Core的源码,这将会是一个很好的学 ...

  7. signature hdr data: BAD, no. of btyes(9088) out of range 问题排查与解决方案

    在使用yum工具安装gcc的时候,报出了signature hdr data: BAD, no. of btyes(9088) out of range 的问题 这是由于centos8中rpm工具存在 ...

  8. 【Azure 应用服务】Azure Function 中运行Powershell 脚本,定位 -DefaultProfile 引发的错误

    问题描述 突然之间,使用PowerShell脚本 Get-AzVirtualNetwork 获取虚拟网络信息时,如果带上  -DefaultProfile $sub 参数,就出现 Azure cred ...

  9. 基于 Nebula Graph 构建百亿关系知识图谱实践

    本文首发于 Nebula Graph Community 公众号 一.项目背景 微澜是一款用于查询技术.行业.企业.科研机构.学科及其关系的知识图谱应用,其中包含着百亿级的关系和数十亿级的实体,为了使 ...

  10. Nebula Graph 源码解读系列 | Vol.06 MATCH 中变长 Pattern 的实现

    目录 问题分析 定长 Pattern 变长 Pattern 与变长 Pattern 的组合 执行计划 拓展一步 拓展多步 保存路径 变长拼接 总结 MATCH 作为 openCypher 语言的核心, ...