概述
Vue 是一个现代 JavaScript 框架,提供了有用的设施渐进增强——不像许多其他框架,你可以使用 Vue 增强现有的 HTML。这使你可以使用 Vue 作为 jQuery 等库的直接替代品。
安装 Vue
要在现有站点中使用 Vue,可以通过 <script> 元素在页面中使用。这使你可以开始在现有站点上使用 Vue,这就是 Vue 引以为傲的渐进式框架的原因。当使用 JQuery 这样的库将现有项目迁移到 Vue 时,这是一个很好的选择。通过这种方法,你可以使用 Vue 的许多核心功能,例如属性、自定义组件和数据管理。
- 开发环境版本,包含了有帮助的命令行警告
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
- 生产环境版本,优化了尺寸和速度,建议你在站点上包含 Vue 时指定版本号,这样任何框架更新都不会影响你的网站。
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
为了使使用 Vue 构建应用程序更容易,有一个 CLI 来简化开发过程。要使用 npm 软件包和 CLI,你需要:
安装 CLI,终端中运行以下命令:
npm install --global @vue/cli
如果你使用 yarn:
yarn global add @vue/cli
安装之后,要初始化一个新项目,可以在要创建项目的目录中打开一个终端,并运行 vue create <project-name>
。
初始化一个新项目
在终端,用 cd
命令进入你想要创建示例的文件夹,然后执行 vue create moz-todo-vue
。你可以选择默认选项 Default ([Vue 3] babel, eslint)
然后按下键盘上的 Enter 继续。CLI 现在将开始构建你的项目,并安装所有依赖项。
然后脚手架工具就开始构建项目,并且安装所需的依赖。
如果你以前从未运行过 Vue CLI,则会再有一个问题——你将被要求选择一个包管理器,它默认为 yarn。从现在开始,Vue CLI 将默认使用此包管理器。如果你此后需要使用不同的包管理器,则可以在运行 vue create
时传入参数 --packageManager=<package-manager>
。因此,如果你想要使用 npm
创建 moz-todo-vue
项目,并且之前选择了 yarn
,则应运行 vue create moz-todo-vue --packageManager=npm
。
项目结构
package.json
:该文件包含项目的依赖项列表,以及一些元数据和eslint
配置。yarn.lock
:如果你选择yarn
作为你的包管理器,将生成此文件,其中包含项目所需的所有依赖项和子依赖项的列表。babel.config.js
:这个是 Babel 的配置文件,可以在开发中使用 JavaScript 的新特性,并且将其转换为在生产环境中可以跨浏览器运行的旧语法代码。你也可以在这个里配置额外的 babel 插件。jsconfig.json
:这是一份用于 Visual Studio Code 的配置文件,它为 VS Code 提供了关于项目结构的上下文信息,并帮助自动完成。public
:这个目录包含一些在 Webpack 编译过程中没有加工处理过的文件(有一个例外:index.html 会有一些处理)。favicon.ico
:这个是项目的图标,当前就是一个 Vue 的 logo。index.html
:这是应用的模板文件,Vue 应用会通过这个 HTML 页面来运行,也可以通过 lodash 这种模板语法在这个文件里插值
src
:这个是 Vue 应用的核心代码目录
.vue 文件(单文件组件)
就像很多其他的前端框架一样,组件是构建 Vue 应用中非常重要的一部分。组件可以把一个很大的应用程序拆分为独立创建和管理的不相关区块,然后彼此按需传递数据,这些小的代码块可以方便更容易的理解和测试。
在其他框架都鼓励把模板、逻辑和样式的代码区分成不同文件的时候,Vue 却反其道行之。使用单文件组件,Vue 把模板、相关脚本和 CSS 一起整合放在 .vue
结尾的一个单文件中。这些文件最终会通过 JS 打包工具(例如 Webpack)处理,这意味着你可以使用构建时工具。你可以使用比如 Babel、TypeScript、SCSS 等来创建更多复杂的组件。
另外,使用 Vue CLI 创建的项目被配置为在开箱即用的情况下借助 Webpack 使用 .vue
文件。实际上,如果你查看我们使用 CLI 创建的项目中的 src
文件夹,你会看到第一个.vue
文件:App.vue
。
App.vue
打开 App.vue
文件,可以看到由 <template>
、<script>
和 <style>
三部分组成,分别包含了组件的模板、脚本和样式相关的内容。所有的单文件组件都是这种类似的基本结构。
<template>
包含了所有的标记结构和组件的展示逻辑。template 可以包含任何合法的 HTML,以及一些我们接下来要讲的 Vue 特定的语法。
<script>
包含组件中所有的非显示逻辑,最重要的是,<script>
标签需要默认导出一个 JS 对象。该对象是你在本地注册组件、定义属性、处理本地状态、定义方法等的地方。在构建阶段这个包含 template 模板的对象会被处理和转换成为一个有 render()
函数的 Vue 组件。
对于 App.vue
,我们的默认导出将组件的名称设置为 App
,并通过将 HelloWorld
组件添加到 components
属性中来注册它。以这种方式注册组件时,就是在本地注册。本地注册的组件只能在注册它们的组件内部使用,因此你需要将其导入并注册到使用它们的每个组件文件中。这对于拆包/摇树优化(tree shaking)很有用,因为并不是应用程序中的每个页面都不一定需要每个组件。
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
// 可以在这里本地注册组件。
HelloWorld,
},
};
备注: 如果想要使用 TypeScript 语法,你应该将 <script>
标签的 lang
属性设置为 <script lang="ts">
来告诉编译器你要使用 TypeScript。
组件的 CSS 应该写在 <style>
标签里,如果你添加了 scoped
属性(形如 <style scoped>
),Vue 会把样式的范围限制到单文件组件的内容里。这个是类似于 CSS-in-JS 的解决方案,只不过允许书写纯粹的 CSS。
备注: 如果通过 CLI 创建项目时选择了 CSS 预处理器,则可以将 lang
属性添加到 <style>
标签中,以便 Webpack 可以在构建时处理内容。例如,<style lang ="scss">
将允许你在样式信息中使用 SCSS 语法。
本地运行程序
Vue CLI 带有内置的开发服务器。这样一来,你就可以在本地运行你的应用程序,这样就可以轻松对其进行测试,而无需自己配置服务器。CLI 会以 npm 脚本的形式将 serve
命令添加到项目的 package.json
文件中,因此你可以轻松地运行它。
在你的终端中,尝试运行 npm run serve
(或者如果希望使用 yarn,则运行 yarn serve
)。你的终端应输出类似以下内容:
INFO Starting development server... 98% after emitting CopyPlugin DONE Compiled successfully in 18121ms App running at: - Local: <http://localhost:8080/> - Network: <http://192.168.1.9:8080/> Note that the development build is not optimized. To create a production build, run npm run build.
如果在浏览器新选项卡打开“本地”地址(如上所述,该地址应类似于 http://localhost:8080
,但可能会因设置而异),你应该会看到你的应用。现在,它应该包含欢迎消息、Vue 文档的链接、使用 CLI 初始化应用程序时添加的插件的链接,以及指向 Vue 社区和生态系统的其他有用链接。
创建第一个Vue组件
Vue 组件是由管理应用程序数据的 JavaScript 对象和映射到基础 DOM 结构的基于 HTML 的模板语法组成的。
我们将从创建一个组件来表示待办事项列表中的每个项目开始。在这一过程中,我们将学习一些重要的概念,例如在其他组件中调用组件,通过道具向它们传递数据,以及保存数据状态。
- 在你的
moz-todo-vue/src/components
目录下,创建一个ToDoItem.vue
的新文件。在你的代码编辑器中打开该文件。 - 通过在文件顶部添加
<template></template>
来创建组件的模板部分。 - 在你的模板部分下面创建一个
<script></script>
部分。在<script>
标签内,添加一个默认导出对象export default {}
,这是你的组件对象。
<template> </template>
<script>
export default {};
</script>
现在我们可以开始为ToDoItem
添加实际内容了。Vue 模板目前只允许一个根元素--一个元素需要包裹模板内的所有内容(Vue 3 发布后会改变这种情况)。我们将为该根元素使用一个<div>。
- 现在在你的组件模板中添加一个空的
<div>
。 - 在那个
<div>
里面,让我们添加一个checkbox
和一个对应的label
。给复选框添加一个id
,并添加一个for
属性,将复选框映射到标签上,如下所示:<template> <div> <input type="checkbox" id="todo-item" checked="false" /> <label for="todo-item">My Todo Item</label> </div> </template>
在应用程序中使用TodoItem组件
- 再次打开
App.vue
文件。 - 在
<script>
标签的顶部,添加以下内容来引入ToDoItem
组件:import ToDoItem from "./components/ToDoItem.vue";
- 在你的组件对象里面,添加
components
属性,然后在它里面添加你的 ToDoItem 组件进行注册。
你的<script>
内容现在应该是这样的:
import ToDoItem from "./components/ToDoItem.vue";
export default {
name: "app",
components: {
ToDoItem,
},
};
这和之前 Vue CLI 注册HelloWorld
组件的方式是一样的。
要在应用程序中实际展示 ToDoItem
组件,你需要在 <template>
模板内添加一个 <to-do-item></to-do-item>
元素。请注意,组件文件名及其在 JavaScript 中的表示方式总是用大写驼色(例如 ToDoList
),而等价的自定义元素总是用连字符小写(例如 <to-do-list>
)。
- 在
<h1>
下面,创建一个无序列表 (<ul>
),其中包含一个列表项 (<li>
)。 - 在列表项 (<li>) 里面添加
<to-do-item></to-do-item>
.
你的App.vue
的<template>
内容现在应该是这样的:
<div id="app">
<h1>To-Do List</h1>
<ul>
<li>
<to-do-item></to-do-item>
</li>
</ul>
</div>
如果你再次查看你的应用程序的渲染情况,你现在应该看的到渲染的ToDoItem
组件,由一个复选框和一个标签组成。
使用props让组件动态化
我们的 ToDoItem
组件仍然不太可用,因为我们只能在页面上包含它一次(ID 必须唯一),而且我们没有办法设置 label 标签的文本。这一切都不是动态的。
我们需要的是一些组件状态。这可以通过在组件中添加 props 来实现。你可以认为 props 与函数中的输入类似。prop 的值给予了组件影响其显示的初始状态。
注册props
在 Vue 中,注册 props 的方式有两种:
- 第一种方式是,以字符串数组的方式列出 props,数组中的每个实体对应一个 prop 名称。
- 第二种方法是将 props 定义为一个对象,每个 key 对应于 prop 名称。将 props 列为对象允许你指定默认值,将 props 标记为 required,执行基本的对象类型 (特别是 JavaScript 基本类型) ,并执行简单的 prop 校验。
针对 ToDoItem 组件,我们将使用对象注册法。
- 回到
ToDoItem.vue
文件。 - 在默认导出的
default {}
对象中添加一个props
属性,该 props 属性含有一个空对象。 - 在这个对象里,添加两个 key 为
label
和done
属性。 label
的值应该是一个带有两个属性的对象(或者是 props,因为它们被调用在可找到的组件的 context)- 第一个
required
属性,它的值是true
. 这将会告诉 Vue 说,我们希望每个该组件的实例都必须有个 label 字段。如果ToDoItem
组件没有 label 字段的话,Vue 会提示警告。 - 第二是添加一个
type
属性。这个属性的值设为 JavaScript 的String
类型。这等于告诉 Vue,我们希望 type 属性的值是 String 类型的。
- 第一个
- 现在转向
done
prop.- 首先添加一个
default
属性,它的值是false
。这意味着当没有done
prop 被传递给ToDoItem
组件时,done
prop 的值会是 false(注意 default 属性不是必需的————我们只在非 required props 里才需要default
) - 接着,添加一个
type
属性,值为Boolean
。这将告诉 Vue,我们希望这个 prop 的值是 JavaScript 的 Boolean 类型。
- 首先添加一个
你的组件对象现在看起来应该像是这样:
<script>
export default {
props: {
label: { required: true, type: String },
done: { default: false, type: Boolean }
}
};
</script>
使用已注册的props
随着组件对象中这些 props 的定义,我们可以在 template 里使用这些变量值。让我们开始向组件模版中添加 label
prop。
在你的 <template>
中,将 <label>
标签的 contents 内容修改为 {{label}}
。
{{}}
是 Vue 中的一个特殊的模版语法,它能在模版内打印类中定义的 JavaScript 表达式的结果,包括值和方法。重要的是,{{}}
里的内容是作为文本显示,而非 HTML。在此例中,我们打印的是 label
的值。
现在,你组件的 template 部分应该是像这样:
<template>
<div>
<input type="checkbox" id="todo-item" checked="false" />
<label for="todo-item">{{label}}</label>
</div>
</template>
回到网页浏览器中,你将会看到 todo item 与之前相同,但是没有 label。转到浏览器的开发者工具,你会在控制台中看到这样的警告:
[Vue warn]: Missing required prop: "label" found in ---> <ToDoItem> at src/components/ToDoItem.vue <App> at src/App.vue <Root>
这是因为我们将 label
prop 标记为 required, 但我们从未给组件这个 prop————我们已经在 template 内定义了希望使用这个 prop 值的位置,但在调用时我们没有把它传递进组件。让我们修复这个问题。
在我们的 App.vue
文件中,像常规 HTML 属性那样,在 <to-do-item></to-do-item>
里添加一个 label
属性:
<to-do-item label="My ToDo Item"></to-do-item>
现在你会在页面上看到 label 了,并且 console 里不会再出现警告提示。
这就是一个简单的 props。接下来我们将讨论 Vue 如何持久化数据状态