单文件组件
Vue单文件组件是指使用由Vue定义的.vue
格式的文件。.vue
文件模板如下:
<!-- Vue 只能包含以下三种标签 -->
<!-- 组件的结构 -->
<template>
<!-- ... -->
</template>
<!-- 组件交互相关的代码(数据、方法等等) -->
<script>
export default {
// ...
};
</script>
<!-- 组件的样式 -->
<style>
/* ... */
</style>
其中:
-
<template>
:用于定义组件的结构。相当于组件配置中的template
配置项。和Html中的
<template>
一样,它不会影响页面最终的结构。由于
<template>
不会影响页面结构,所以在<template>
中还需要定义一个元素作为整个组件的根节点。 -
<script>
:定义组件的交互相关的代码。即定义创建组件的JS代码。在
<script>
中可以使用Vue.extend()
来创建组件。但是由于Vue会在需要的时候帮我们自动调用Vue.extend()
,所以Vue.extend()
可省略。一般情况下export default
组件的配置对象即可。如果要使用
Vue.extend()
,需要先引入Vue
。 -
<style>
:和Html中的<style>
一样,都是用于定义样式。 -
.vue
注释:.vue
中的文件有4个地方可以写注释:-
<template>
中:使用Html的注释<!-- 注释内容 -->
。 -
<script>
中:使用JS的注释// 注释内容
或/* 注释内容 */
。 -
<style>
中:使用CSS的注释/* 注释内容 */
。 -
上述范围之外的其它地方:也就是在
<template>
、<script>
和<style>
之外的其它地方可以使用注释。这些注释是属于.vue
文件自己的注释,一共有3种注释类型:<!-- 注释内容 --> // 注释内容 /* 注释内容 */
也就是说,
<template>
、<script>
和<style>
之外的其它地方可以使用Html、JS和CSS的任何类型的注释。
-
Vue CLI
由于浏览器并不支持直接浏览.vue
类型的文件,所以需要将.vue
类型的文件编译成浏览器支持的文件类型。而Vue CLI(Vue Command Line Interface,Vue脚手架)可以帮助我们快速地编译.vue
。
安装 Vue CLI
Vue CLI需要使用npm
安装,请确保你的电脑上已经安装了Node.js。
Vue CLI安装命令如下:
npm install -g @vue/cli
安装完成后直接使用vue
命令运行Vue CLI。查看Vue CLI版本以验证是否安装成功:
vue -V
使用 Vue CLI
使用Vue CLI创建一个项目:
vue create vue_demo
接着Vue CLI会让你选择一个默认的配置:
使用键盘的↑
或↓
去移动选择,然后按下回车即可开始创建。
其中的
babel
是用来将ES6的代码转换为ES5。eslint
是用来进行语法检查。
出现如下提示表示项目创建成功:
🎉 Successfully created project vue_demo.
👉 Get started with the following commands:
$ cd vue_demo
$ npm run serve
根据提示信息可以知道,进入vue_demo
目录之后运行npm run serve
可以启动这个项目:
cd vue_demo
npm run serve
启动成功后,项目服务的默认端口是8080
,可以访问http://localhost:8080/
以浏览Vue CLI为我们创建的HelloWorld
这个项目示例。
项目结构
Vue CLI创建好的项目结构一般如下:
vue_demo
├── babel.config.js
├── dist
├── .git
├── .gitignore
├── jsconfig.json
├── package.json
├── package-lock.json
├── public
│ ├── favicon.ico
│ └── index.html
├── README.md
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ ├── Hello.vue
│ │ └── SiteUser.vue
│ └── main.js
└── vue.config.js
在创建好的vue_demo
中,有以下这些注意点:
-
.gitignore
:排除那些不需要被git
所管理的文件或目录。 -
babel.config.js
:babel
的配置文件。一般来说不需要修改该配置,如果需要修改,可以浏览Babel官网 -
package.json
:当前(Node.js)项目的包管理配置文件。其中需要注意一下的是:
{ /* ... */ "scripts": { "serve": "vue-cli-service serve", // 预览项目 "build": "vue-cli-service build", // 构建项目 "lint": "vue-cli-service lint" // 进行语法检查 }, /* ... */ }
-
READNE.md
:程序说明文档。 -
src
:项目源代码文件。在使用默认配置的情况下,名称不可随意更改。src
的结构如下所示:main.js
:默认的项目入口文件,主要用来创建Vue实例。在使用默认配置的情况下,名称不可随意更改。App.vue
:项目中所有组件的根组件。assets
:存放项目的静态资源。components
:存放项目中(除了App.vue
)组件的文件夹。
-
public
:存放index.html
、favicon.ico
等文件。在使用默认配置的情况下,名称不可随意更改。public/index.html
是当前项目默认打开的页面。在使用默认配置的情况下,名称不可随意更改。在
index.html
中,有一个最重要的东西:<div id="app"></div>
-
vue.config.js
:Vue CLI的配置文件(可选),与package.json
同级。
Vue CLI 入口文件
在main.js
中的import Vue from 'vue'
和render: h => h(App)
语句需要格外注意:
main.js
中,使用ES6引入的Vue(即import Vue from 'vue'
),是vue.runtime.esm.js
。
vue.runtime.esm.js
是一个精简版的Vue,其中去除了原本Vue中的模板解析器。所以在main.js
的Vue实例中,使用template
配置项会因为没有模板解析器而导致无法解析。
有两种方法可以解决该问题:
-
引入完整版的
vue.js
:import Vue from 'vue/dist/vue' // 引入 Vue import App from './App.vue' // 引入 App 组件 /* ... */ new Vue({ components: {App}, template: `<App>Hello!</App>`, }).$mount('#app')
-
使用
render
配置项:import Vue from 'vue' // 引入 Vue import App from './App.vue' // 引入 App 组件 /* ... */ new Vue({ render: h => h(App), }).$mount('#app')
render
本质是Vue调用的一个函数,它需要接收一个参数createElement
这个参数是function
类型。createElement()
可以帮助我们在页面中创建并渲染元素。例如:import Vue from 'vue' // 引入 Vue // 其实这里也可以使用完整版的 Vue,但是没必要 /* ... */ new Vue({ render(createElement) { console.log('render.'); console.log(typeof createElement); // function return createElement('h2', 'Hello!') }, }).$mount('#app')
由于
render
中不需要使用this
,所以可以使用Lambda表达式() => {}
来定义。如上方的解决方案中h => h(App)
就是render
最简洁的定义方式。使用了
render
就无需使用components
。
注:在
.vue
中依旧是使用<template>
和components
。也就是说,实例无需使用render
。
Vue CLI 配置文件
Vue CLI默认的入口文件就是main.js
。并且Vue CLI隐藏了所有webpack
相关的配置,若想查看具体的webpack
配置,可运行:
vue inspect > output.js
将Vue CLI的webpack
相关配置输出到output.js
这个文件中(仅用作输出浏览,无法在此更改配置)。
在Vue CLI的webpack
相关配置中有这样的内容:
{
/* ... */
entry: {
app: [
'./src/main.js' // 项目入口文件
]
}
}
要修改这些配置内容,需要在vue.config.js
中进行修改。它的基本形式如(使用的是common.js
的模块化语法):
module.exports = {
/* 选项... */
}
或使用@vue/cli-service
提供的defineConfig()
帮手函数:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
/* 选项... */
})
vue.config.js
中有一个pages
配置项(具体内容可在官方文档中复制):
module.exports = {
/* ... */
pages: {
index: {
// page 的入口
entry: 'src/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: 'Index Page',
}
}
}
除了pages
配置选项,还有用于关闭语法检查的lintOnSave
:
module.exports = {
lintOnSave: false
}
vue.config.js
的配置选项可参考 Vue CLI 配置参考。
注:
vue.config.js
被修改之后,需要重新运行npm run serve
。如果在
vue.config.js
中类似这样配置:module.exports = { pages: { index: { /* 空的配置内容 */ } } }
那么在启动或者构建项目的时候就会发生错误。因为此时的配置中的
pages.index
传递的是一个没有任何属性的对象,而Vue CLI并不会去解析它并为他配上默认的内容。所以在使用
vue.config.js
的时候,要么干脆不添加配置选项,使用默认的内容;要么就要按照配置选项的内容进行正确的配置。
Vue 包
Vue的依赖包在node_modules/vue/dist
中。其中有这么些版本:
-
.esm
:包含.esm
的文件代表使用了ES6的模块化语法。使用ES6的模块化语法的版本,浏览器无法直接使用。 -
.min
:包含.min
就是指压缩版本。 -
完整版:
vue.js
:浏览器可以直接使用的完整版本。vue.esm.js
:使用了ES6的模块化语法的完整版。
-
runtime
:运行时版本,是Vue的精简版本,去除了模板解析器。vue.runtime.js
vue.runtime.min.js
vue.runtime.esm.js
runtime
版本不能使用template
配置项。需要使用render
函数接收到的createElement
函数去指定具体内容。 -
common
:使用common.js
时使用的版本。vue.common.js
vue.common.dev.js
vue.common.prod.js
vue.runtime.common.dev.js
vue.runtime.common.js
vue.runtime.common.prod.js
Vue CLI中
<template>
标签配置的模板,是由vue-template-compiler
(Vue 模板解析器)来解析。这个vue-template-compiler
只能解析.vue
中的<template>
模板,而不能解析template
配置项。
示例
根据以上步骤和信息,将非单文件组件中的site
和user
定义为单文件组件的形式:
PS:由于使用的Vue CLI版本为5,默认开启语法检查。根据ESLint的官方代码规范,除了
App
的其它组件只能以multi-word
(多单词)的形式命名。所以下方组件的命名遵循ESLint规范。
multi-word
形式选择kebab-case或CameCase都可以。
-
MySite
:<template> <div class="my-site"> <h2>网站名称:{{name}}</h2> <h2>网站地址:{{url}}</h2> </div> </template> <script> export default { name: 'MySite', data() { return { name: 'Linner\'s Blog', url: 'blog.linner.asia', } }, }; </script> <style> .my-site { background-color: yellow; } </style>
-
SiteUser
:<template> <div> <h2>用户姓名:{{name}}</h2> <h2>用户年龄:{{age}}</h2> </div> </template> <script> export default { name: 'SiteUser', data() { return { name: '张三', age: 18, } }, } </script>
-
App.vue
:<template> <div> <img src="./assets/logo.png" alt="logo"> <MySite/> <hr> <SiteUser/> </div> </template> <script> // 引入组件 import MySite from "./components/MySite.vue"; import SiteUser from './components/SiteUser.vue'; export default { name: 'app', components: { MySite, SiteUser, } } </script>
其它文件暂时不用改动。然后在项目目录下运行npm run serve
即可预览。
组件化编码流程
- 拆分静态组件:组件按功能点拆分,命名不要与Html元素冲突。
- 实现动态组件:根据数据被使用的范围,考虑好数据的存放位置。
- 数据只有一个组件在使用:放在组件中即可。
- 数据被一部分组件共同使用:放在这些组件的父组件上(这种方法被称为状态提升,Vue中的数据也可被称为状态)。
- 实现交互:从绑定事件开始。
评论