文章目录
- 1. 脚手架—vue-cli
- 2. 单文件组件
- 3. 扩展
- 3.1 本地搭建服务
- 3.2 自定义脚手架配置
- 3.2.1 publicPath
- 3.2.2 outputDir
- 3.2.3 [@](https://cli.vuejs.org/zh/config/#assetsdir)assetsDir
- 3.2.4 indexPath
- 3.2.5 [@](https://cli.vuejs.org/zh/config/#filenamehashing)filenameHashing
- 3.2.6 [@](https://cli.vuejs.org/zh/config/#pages)pages
- 3.2.7 devServer
- 3.2.8 [@](https://cli.vuejs.org/zh/config/#devserver-proxy)devServer.proxy
- 3.2.9 vue-router—分析install源码
1. 脚手架—vue-cli
之前我们所讲述内容,都围绕的script
标签引入的。
vue
的脚手架工具和React
的脚手架工具一样,综合了很多东西,如打包、构建、单元测试等,它其实就是一个集成开发环境,提供了很多工具。
Vue 提供了一个脚手架工具,帮助我们快速搭建本地项目:vue-cli
vue-cli 是 vue 提供的一个用于自动化构建和开发项目的工具,也称为:脚手架,它是一系列工具的集合,它主要有:
- 根据配置选项自动构建项目,并安装所需要的依赖
- 启动一个本地开发服务器,通过这个服务器可以基于服务器环境访问本地项目,同时提供了跨域代理服务
- 项目的自动编译、打包
- 项目测试(单元测试、e2e测试)
1.1 安装
npm install -g @vue/cli
// OR
yarn global add @vue/cli
看是否安装成功,可以输出vue
命令
有点类似create-react-app
脚手架工具,但是它提供了更多地特性。
查看版本
vue --version
// OR
vue -V
帮助
vue --help
// OR
vue -h
1.2 创建项目
vue-cli 提供了两种使用方式
- 命令行-cli
- 图形界面(基于浏览器) - UI
// 命令行
vue create 项目名称
// UI
vue ui
运行命令以后,根据提示进行选择
1.2.1 命令行方式创建项目
vue create 项目名称
vue create app
进入一个交互式页面:
第一个提示使用上下键选择,想要的选项:
默认配置(安装babel、eslint
)
手动配置(手动选择特性)
选择第二个回车,然后选择可以用到的去安装
提示 空格
选择、a
全选 、 i
反选
PWA
渐进式web应用
Vuex
状态管理方案
CSS Pre-processors
CSS预处理器
Linter / Formatter
代码格式化、代码标准(代码规范)
Unit Testing
单元测试
E2E Testting
端到端测试,模拟用户与浏览器的交互,但不是人点,而是通过代码打开浏览器,用代码模拟人操作
选择完后,回车安装:
In dedicated config files: 单独保存在各自的配置文件中 => 刚才选择安装文件最终形成一个配置文件,可单独存放
In package.json: 保存在package.json文件中 => 融入package.json
选第一个
提示,是否把配置存起来,以备下次直接使用。
选n
,开始安装
运行
项目创建成功以后,进入项目根目录,打开 package.json 文件,我们可以看到
{
...,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
...
}
https://cli.vuejs.org/zh/guide/cli-service.html#%E4%BD%BF%E7%94%A8%E5%91%BD%E4%BB%A4
cd app
yarn serve
1.2.2 UI式交互 —基于浏览器图形界面方式创建项目
vue ui
vue ui
安装完成后
1.2.3 扩展—什么是渐进式web应用?
PWA
应用是指那些使用指定技术和标准模式来开发的web应用
,这将同时赋予它们web应用
和原生应用
的特性。
例如,web应用
更加易于发现——相比于安装应用,访问一个网站显然更加容易和迅速,并且你可以通过一个链接来分享web应用
。
在另一方面,原生应用与操作系统可以更加完美的整合,也因此为用户提供了无缝的用户体验。你可以通过安装应用使得它在离线的状态下也可以运行,并且相较于使用浏览器访问,用户也更喜欢通过点击主页上的图标来访问它们喜爱的应用。
PWA
赋予了我们创建同时拥有以上两种优势的应用的能力。
这并不是一个新概念——这样的想法在过去已经在web平台
上通过许多方法出现了多次。渐进式增强和响应式设计已经可以让我们构建对移动端友好的网站。在多年以前的Firefox OS
的生态系统中离线运行和安装web应用
已经成为了可能。
PWAs
, 不但如此,更是提供了所有的甚至是更多的特性,来让web更加优秀。
1.3 打包
npm build
yarn build
最终丢到服务器的代码就是dist
里的文件。
1.4 目录结构
- node_modules/ 安装的第三方插件及依赖
- public/ 应用的index.html,打包后的文件最终的入口
- src/ 开发过程中的目录
- assets/ 开发用到的资源(通过import引入),如图片
- components/ 组件
- app.vue
- main.js 应用入口
- ... 几乎都是配置文件等,不是重点
src
先来说一个最重要的目录 src ,这个就是存放的就是我们项目源码的目录,我们开发过程中大部分的时间就在这个目录中
- main.js
项目的入口文件
- App.vue
首先,这是 vue 提供的一种单文件组件的文件模式(后续会讲),一个 .vue 文件就是一个独立的组件,这里的 App.vue 是应用的根组件
- components 目录
存放组件的目录
- assets 目录
存放静态资源的目录,比如:图片,css 等。这里的文件与外层 public 目录存放的静态资源的最大区别是:assets 存放的资源是通过 import 等方式作为模块导入,最后打包处理的。而 public 中的资源并不通过模块方式导入,一般都是通过 script 、link 、img 等方式从浏览器引入的资源,比如无法通过模块化处理的 js 文件(这样的需求情况并不多)
public
一些并非通过模块方式引入的资源文件存放的位置,一般都是通过 script 、link 、img 等方式从浏览器引入的资源,比如无法通过模块化处理的 js 文件(这样的需求情况并不多)
\test01\app\src\main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false // Vue 在启动时的生产提示
// 构建根组件
new Vue({
// 没有采用template,而是render
render: h => h(App), // 对jsx进行渲染,h就是似虚拟dom的构建函数,类似react的dom底下的create方法,然后把组件传进去,进行渲染
}).$mount('#app') // 挂载到页面id的app上
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.56
Branch: branch04commit description:a1.56(vue脚手架工具构建项目)
tag:a1.56
vue
为了方便进行组件开发,特意弄了.vue
的文件,它帮助我们更为方便地进行组件开发,不过该文件不能直接被浏览器解析。实际上在webpack
中加了vue-loader
,最终被webpack
解析成一个js
文件,它返回回去的是一个对象(templete
、样式等均组织到一个对象里与它进行融合)。
实际返回回去就是一个组件对象。
\app\src\App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
2. 单文件组件
vue 的单文件组件是官方提供的一种用来组织组件代码的形式,该文件以 .vue
为后缀,该文件会被 vue-cli 内置的 webpack 解析生成对应的 javascript、html、css 文件
https://vue-loader-v14.vuejs.org/zh-cn/start/spec.html
vue 也是基于组件的开发模式,我们知道一个 UI 组件包含
- 结构
- 样式
- 行为
为了能够更加方便的编写组件,vue 提供了一个特殊的组件定义文件:.vue 文件,我们也称为 单文件组件
2.1 组成
一个单文件组件的 结构、样式、行为 分别通过三个标签来进行定义和划分(方便对组件进行编写)
<html>
<script>
<style>
单文件组件把一个组件所包含的 结构、样式、行为 分别通过 template、style、script 进行分离包含,然后统一组织在一个文件中
注意:一个单文件组件最少必须包含 template,可以不需要 script 和 style
2.2 lang (language)属性
无论是 template、script 还是 style,都可以通过 lang 属性来指定它们所使用的语言
template默认是html
语言,我们这里设置成jade
script默认是js
,这里改成用ts
。
<template lang="jade">
div.example
p {{ msg }}
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
data () {
return {
msg: 'Hello world'
}
}
})
</script>
<style lang="stylus">
.example
color red
</style>
2.3 src 属性
如果一个组件的模板脚本内容太多了,导致文件太大,可以把template、style、script 进行分离
可以通过 src 属性把文件分离到单独的文件中
<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>
这里的 src 同样遵循模块化的导入规则,
./
开头的表示相对路径,/
开头表示 NPM 包中的资源
2.4 有作用域的 CSS
当 style
标签有 scoped
属性时,它的 CSS 只作用于当前组件中的元素。这类似于 Shadow DOM 中的样式封装
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
解析后:
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
2.4.1 example01
2.4.1.1 example01-1
\app\src\components\HelloWorld.vue
<template>
<div class="hello">
<p>这里是hello - {{msg}}</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<style>
</style>
\app\src\App.vue
<template>
<div id="app">
<h1>软件开发</h1>
<p>前端Vue</p>
<hr>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
vue脚手架demo\app\src\components\HelloWorld.vue
<template>
<div class="hello">
<p>这里是hello - {{msg}}</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<style>
p {
color: red;
}
</style>
vue脚手架demo\app\src\App.vue
<template>
<div id="app">
<h1>软件开发</h1>
<p>前端Vue</p>
<hr>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
我们发现这里会有一个问题 =>
编译后的html
的样式,这个样式会影响全局。它把全部的p
标签(组件里和组件外的p
标签),但是封装组件的目的是使数据、模板是独立的,样式也应该使独立的。
但是CSS
中没有默认作用域的问题,所以它采取了一个特别的手段,加载了一个第三方模块,主要用来处理CSS module
的(模块问题)。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.57
Branch: branch04commit description:a1.57(example01-1——css无独立作用域的隐患)
tag:a1.57
2.4.1.2 example01-2
<style scoped>
p{
color: red;
}
</style>
scoped
它会使组件相关的模板,都加了data-v-469af010
,469af010
是一个hash值,每一个组件都有自己独立的hash
值。组件中所有标签都会加上该属性,并且在css
中加一个选择器data-v-469af010
,这样就只会处理该类组件的标签元素了。这样就解决css
作用域的问题了。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.58
Branch: branch04commit description:a1.58(example01-2——用scoped解决css无独立作用域的隐患)
tag:a1.58
2.4.2 混用本地和全局样式
<style>
/* 全局样式 */
</style>
<style scoped>
/* 本地样式 */
</style>
2.5 资源路径处理
在项目开发中,我们经常会碰到要引入外部资源的需求,vue 单文件系统中,对资源引入路径有一定的特殊处理
- 绝对路径前缀
- 相对路径前缀
- 特殊前缀
2.5.1 example02
\app\src\components\HelloWorld.vue
<template>
<div class="hello">
<p>这里是hello - {{msg}}</p>
<img src="../assets/logo.png" alt="">
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<style scoped>
p{
color: red;
}
</style>
Webpack
会将其作为模块进行打包,然后把它构建生成到指定的目录里。
但现在有一个问题是,Webpack
有一个http
服务(Webpack server
),它生成后把所有的编译内容都是存在内存中的,没有真正地生成文件,在这里是找不到最终打包的东西的(都在内存中)。
如果想上线开发完成了,这个时候才能使用build
命令,对其进行构建,才能在硬盘中生成。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.59
Branch: branch04commit description:a1.59(example02——引入图片资源)
tag:a1.59
2.5.2 绝对路径前缀
就是以 /
、https://www.csdn.net/
等这样的绝对路径开头的(不会被Webpack解析),不做任何处理,保持原样地址不动,直到被浏览器解析。
2.5.2.1 example03
2.5.2.1.1 example03-1
vue04\vue脚手架demo\app\src\components\HelloWorld.vue
<template>
<div class="hello">
<p>这里是hello - {{msg}}</p>
<img src="/assets/logo.png" alt="">
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<style scoped>
p {
color: red;
}
</style>
现在暂时没有资源,所以访问不到图片。
这个时候就会保持原地址不变,直接交给浏览器处理,由于没这个资源,显然显示不出来。
实际上webpack
会指定一个根目录(public/index.html
),如果把它丢到public
文件夹里。
\app\src\components\HelloWorld.vue
<template>
<div class="hello">
<p>这里是hello - {{msg}}</p>
<img src="/logo.png" alt="">
</div>
</template>
src/assets/
文件夹中文件是需要经过Webpack
打包处理的,作为模块打包的,而public
存放的文件是不需要经过Webpack
打包处理的,而是通过浏览器发送http
请求处理的资源。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.60
Branch: branch04commit description:a1.60(example03-1——相对路径引入图片资源)
tag:a1.60
2.5.2.1.2 example03-2
线上地址也不会被webpack
处理,而是交给浏览器请求。
<template>
<div class="hello">
<p>这里是hello - {{msg}}</p>
<img src="https://csdnimg.cn/cdn/content-toolbar/dragonBoat-white.gif" alt="">
</div>
</template>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.61
Branch: branch04commit description:a1.61(example03-2——引入网上图片资源)
tag:a1.61
2.5.3 相对路径前缀
就是以 ./
、../
这样的相对路径开头的,将会被看作相对的模块依赖,并按照你的本地文件系统上的目录结构进行解析,如:<img src="../a.png">
解析后:<img src="require('../a.png')">
,类似的还包括 background: url(...)
和 @import
。
2.5.4 特殊前缀
- 如果路径以
~
开头,其后的部分将会被看作模块依赖。这意味着你可以用该特性来引用一个 node(NPM 包) 依赖中的资源,如:<img src="~some-npm-package/a.png">
- 如果路径以
@
开头,也会被看作模块依赖。如果你的 webpack 配置中给@
配置了 alias,这就很有用了。所有vue-cli
创建的项目都默认配置了将@
指向/src
2.5.4.1 example04
如果使用相当路径,如果修改了引用资源文件的路径,也得修改资源路径,这样使用也不太好。
以 @
开头,所有 vue-cli
创建的项目都默认配置了将 @
指向 /src
,也会被看作模块依赖。
无论我们的helloword
组件移动到哪,都不会受到影响,都是表示src
目录下的/assets/logo.png
。
\app\src\components\HelloWorld.vue
<template>
<div class="hello">
<p>这里是hello - {{msg}}</p>
<img src="https://csdnimg.cn/cdn/content-toolbar/dragonBoat-white.gif" alt="">
<img src="@/assets/logo.png" alt="">
</div>
</template>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.62
Branch: branch04commit description:a1.62(example04——@特殊前缀的使用)
tag:a1.62
3. 扩展
3.1 本地搭建服务
npx http-server --help
可看帮助
去npm搜指令:
npx http-server ./dist -c-l
3.2 自定义脚手架配置
官网有对应的配置:https://cli.vuejs.org/zh/config/#vue-config-js
我们之前用的都是默认配置,有的时候需要更改一些配置,这个时候可以单独创建一个vue.config.js
文件,类似webpack.config
。
3.2.1 publicPath
-
Type:
string
-
Default:
'/'
部署应用包时的基本 URL。用法和 webpack 本身的
output.publicPath
一致,但是 Vue CLI 在一些其他地方也需要用到这个值,所以请始终使用publicPath
而不要直接修改 webpack 的output.publicPath
。默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上,例如
https://www.my-app.com/
。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在https://www.my-app.com/my-app/
,则设置publicPath
为/my-app/
。这个值也可以被设置为空字符串 (
''
) 或是相对路径 ('./'
),这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径,也可以用在类似 Cordova hybrid 应用的文件系统中。相对 publicPath 的限制
相对路径的
publicPath
有一些使用上的限制。在以下情况下,应当避免使用相对publicPath
:- 当使用基于 HTML5
history.pushState
的路由时; - 当使用
pages
选项构建多页面应用时。
这个值在开发环境下同样生效。如果你想把开发服务器架设在根路径,你可以使用一个条件式的值:
module.exports = { publicPath: process.env.NODE_ENV === 'production' ? '/production-sub-path/' : '/' }
- 当使用基于 HTML5
如:
\test01\app\vue.config.js
- publicPath 默认为
‘/’
—— 如果公司在一个项目上开发一些子项目,就可能有子目录了。
// vue.config.js
module.exports = {
// 选项...
publicPath: '/Web/subindex'
}
yarn serve
3.2.2 outputDir
-
Type:
string
-
Default:
'dist'
当运行
vue-cli-service build
时生成的生产环境构建文件的目录。注意目标目录在构建之前会被清除 (构建时传入--no-clean
可关闭该行为)。提示
请始终使用
outputDir
而不要修改 webpack 的output.path
。
3.2.3 @assetsDir
-
Type:
string
-
Default:
''
放置生成的静态资源 (js、css、img、fonts) 的 (相对于
outputDir
的) 目录。提示
从生成的资源覆写 filename 或 chunkFilename 时,
assetsDir
会被忽略。
如:
// vue.config.js
module.exports = {
// 选项...
publicPath: '/Web/subindex',
assetsDir: './publicSource'
}
yarn build
3.2.4 indexPath
-
Type:
string
-
Default:
'index.html'
指定生成的
index.html
的输出路径 (相对于outputDir
)。也可以是一个绝对路径。
3.2.5 @filenameHashing
-
Type:
boolean
-
Default:
true
默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。然而,这也要求 index 的 HTML 是被 Vue CLI 自动生成的。如果你无法使用 Vue CLI 生成的 index HTML,你可以通过将这个选项设为
false
来关闭文件名哈希。
3.2.6 @pages
-
Type:
Object
-
Default:
undefined
在 multi-page 模式下构建应用。每个“page”应该有一个对应的 JavaScript 入口文件。其值应该是一个对象,对象的 key 是入口的名字,value 是:
- 一个指定了
entry
,template
,filename
,title
和chunks
的对象 (除了entry
之外都是可选的); - 或一个指定其
entry
的字符串。
module.exports = { pages: { index: { // page 的入口 entry: 'src/index/main.js', // 模板来源 template: 'public/index.html', // 在 dist/index.html 的输出 filename: 'index.html', // 当使用 title 选项时, // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title> title: 'Index Page', // 在这个页面中包含的块,默认情况下会包含 // 提取出来的通用 chunk 和 vendor chunk。(首页当中提取的js) chunks: ['chunk-vendors', 'chunk-common', 'index'] }, // 如果还有其他页面,可继续往下配置,根pages一样 // 当使用只有入口的字符串格式时, // 模板会被推导为 `public/subpage.html` // 并且如果找不到的话,就回退到 `public/index.html`。 // 输出文件名会被推导为 `subpage.html`。 subpage: 'src/subpage/main.js' } }
提示
当在 multi-page 模式下构建时,webpack 配置会包含不一样的插件 (这时会存在多个
html-webpack-plugin
和preload-webpack-plugin
的实例)。如果你试图修改这些插件的选项,请确认运行vue inspect
。 - 一个指定了
3.2.7 devServer
-
Type:
Object
所有
webpack-dev-server
的选项都支持。注意:- 有些值像
host
、port
和https
可能会被命令行参数覆写。 - 有些值像
publicPath
和historyApiFallback
不应该被修改,因为它们需要和开发服务器的 publicPath 同步以保障正常的工作。
- 有些值像
3.2.8 @devServer.proxy
-
Type:
string | Object
如果你的前端应用和后端 API 服务器没有运行在同一个主机上,你需要在开发环境下将 API 请求代理到 API 服务器。这个问题可以通过
vue.config.js
中的devServer.proxy
选项来配置。devServer.proxy
可以是一个指向开发环境 API 服务器的字符串:module.exports = { devServer: { proxy: 'http://localhost:4000' } }
这会告诉开发服务器将任何未知请求 (没有匹配到静态文件的请求) 代理到
http://localhost:4000
。如果你想要更多的代理控制行为,也可以使用一个
path: options
成对的对象。完整的选项可以查阅 http-proxy-middleware 。module.exports = { devServer: { proxy: { '/api': { target: '<url>', ws: true, changeOrigin: true }, '/foo': { target: '<other_url>' } } } }
3.2.9 vue-router—分析install源码
npm install vue-router
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a1.63
Branch: branch04commit description:a1.63(安装vue-router)
tag:a1.63
我们看一下打包之前的index.js
源码
这里导出去了VueRouter
,这里面有一个方法是install
,其实既可以传函数,又可以传包装install
方法的对象,如果传的是函数,它就直接执行了。如果传的是对象,就会找对象底下的install
方法,去调用它。最终vue
的使用则是:Vue.use(VueRouter)
,之后就会执行它底下的install
方法了,进行插件安装了。
重点看install
方法源码实现 => 大概分析一下
import View from './components/view'
import Link from './components/link'
export let _Vue
export function install (Vue) {
// 判断插件是否安装了,如果安装了,并且_Vue === Vue,即use多次,不会重复执行install (单例模式)
if (install.installed && _Vue === Vue) return
install.installed = true
_Vue = Vue
// 判断变量v是否定义过
const isDef = v => v !== undefined
// 注册实例 vm:组件对象 vm.$options 组件对象的配置选项
// vm.$options._parentVnode 父组件
const registerInstance = (vm, callVal) => {
let i = vm.$options._parentVnode
// 判断父组件是否注册过,对i进行赋值,赋完值判断data是否存在,判断路由实例是否注册过
if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
// 都判断过了,就会调用父组件的_parentVnode,并把vm组件对象实例及callVal传过去
i(vm, callVal)
}
}
// 做事,每一个组件及子组件,只要有组件一渲染就首先调用路由底下的beforeCreate方法
Vue.mixin({
beforeCreate () {
// 判断创建的Vue对象配置有没有router属性对象,如果有则进行设置及处理
if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
registerInstance(this, this)
},
// 销毁该实例
destroyed () {
registerInstance(this)
}
})
// $router 获取路由对象
Object.defineProperty(Vue.prototype, '$router', {
get () { return this._routerRoot._router }
})
// $route 获取当前匹配的路由对象
Object.defineProperty(Vue.prototype, '$route', {
get () { return this._routerRoot._route }
})
// 创建两个组件
Vue.component('RouterView', View)
Vue.component('RouterLink', Link)
// 创建相关生命周期
const strats = Vue.config.optionMergeStrategies
// use the same hook merging strategy for route hooks
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}
(后续待补充)