Vue 生态如今越来越完善了,随之而来也有了不少的周边。除了前面的 Vue Loader、Vuex、Vue CLI 等常用工具,这里也介绍一些可以使用 Vue 进行开发的周边拓展工具,包括 Vuepress、Vue 生成小程序等。
1. VuePress 快速搭建文档平台
VuePress 是 Vue 驱动的静态网站生成工具,基于 Markdown 维护的文档网站。如果你有自己的博客,那应该也了解过 Hexo 工具,而 VuePress 可以理解为一个 Vue 版本的 Hexo。基于 Vue 和 Webpack 的开发方式,可以让开发者简单又便捷地实现一些想要的功能。
1.1 VuePress 介绍
一个 VuePress 网站其实是一个由 Vue、Vue Router 和 Webpack 驱动的单页应用。虽然和 Nuxt.js 很相似,但相比于 Nuxt.js 用于应用程序的构建,VuePress 专注于以内容为中心的静态网站。VuePress 由两部分组成:
(1) 由 Vue 驱动的极简静态网站生成器。我们在初始化项目之后,只需要添加 Markdown 文档,以及进行简单的配置就可以生成一个功能完备的静态网站(包括菜单、导航、路由、搜索等功能)。
(2) 提供基于技术文档的默认主题(可以参考 Vue 官方主题样式),同时也支持自定义配置主题方式。
对比 Hexo,VuePress 最大的亮点在于,除了通用的 Markdown 能力之外,VuePress 允许在 Markdown 中使用 Vue,也就是说我们写着 Markdown 的过程中可以插入一个 Vue 组件。而基于 Vue 的驱动方式,我们可以使用 Vue 自由地调整默认主题和样式,对于熟悉 Vue 开发的小伙伴来说,开发效率有了质的提升。
1.2 快速开发静态网站
介绍了那么多,我们来看一下使用 VuePress 生成一个静态网站到底有多简单。
安装和使用
首先我们需要安装依赖,完整的开发和构建流程步骤如下。
(1) 安装依赖。
# 全局安装 vuepress npm install -g vuepress # 安装依赖 npm install
(2) 目录结构设计。
为了方便管理,我们创建一个 docs 文件夹,将一些 markdown 文档放在里面维护,文件夹外面就可以做一些简单的依赖管理、脚本等。整体来说,我们的目录结构如下:
├─docs/ // vuepress根目录 │ ├─.vuepress/ // vuepress应用相关 │ │ ├─dist/ // 编译之后的静态文件 │ │ ├─theme/ // 自定义主题 │ │ ├─config.js // 配置 │ │ ├─enhanceApp.js // 应用级别的配置 │ ├─basic/ // 基础类文档 │ ├─vue/ // Vue类文档 │ ├─README.md // 首页文档和配置 │ ├─deploy.sh // 部署到Github脚本 ├─package.json // 项目配置 ├─README.md // 项目说明
VuePress 应用相关的配置都放置在.vuepress 文件夹下,关于自定义主题、配置和应用级别的配置后面会一点点描述。其他的文档归类可根据文档类别进行文件夹的区分,而 docs 下的默认 README.md 则是首页内容。
基于这样的目录结构,我们可以确定如何进行开发和打包,因此可以在 package.json 配置:
{ "scripts": { "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" } }
然后我们可以通过命令来进行:
# 本地开始写作 npm run docs:dev # 构建生成静态文件 npm run docs:build
(3) 文档内容管理填充。
这里我们分了基础类文档和 Vue 类文档,分别放置在docs/basic
和docs/vue
目录下面,在将 markdown 挪到对应的地方之后,我们可以这么进行组织:
├─docs/ // vuepress根目录 │ ├─.... // 其他省略 │ ├─basic/ // 基础类文档 │ │ ├─1/ // 基础类文档分类1 │ │ ├─2/ // 基础类文档分类2 │ │ ├─README.md // 基础类文档默认页 │ ├─vue/ // Vue类文档 │ │ ├─1/ // Vue类文档分类1 │ │ ├─2/ // Vue类文档分类2 │ │ ├─README.md // Vue类文档默认页 │ ├─README.md // 首页文档和配置 │ ├─.... // 其他省略
调整好内容之后,我们来看看要怎么配置。
(4) 首页配置。
默认的主题提供了一个首页(Homepage)的布局这里,我们直接使用它,所以在根级的 README 中进行以下配置:
## <!-- docs/README.md --> home: true # 使用默认主题的首页布局 actionText: 快速阅读 → actionLink: /basic/1/basic-1-1.md features: - title: 基础类文档 details: 基础类文档描述。 - title: Vue 类文档 details: Vue 类文档描述。 - title: 其他补充 details: 其他补充描述。 footer: MIT Licensed | Copyright © 2018-present 被删 ---
(5) 默认配置。
想要项目顺利跑起来,我们还需要补充默认配置,需要在 docs/.express 文件夹下添加 config.js 文件:
// docs/.express/config.js module.exports = { title: "某个前端文档网站", // 首页标题 shouldPrefetch: () => false, // 关闭预加载,可能导致首页渲染比较慢 description: "Just playing around", // 首页描述 themeConfig: { // logo: '/assets/img/logo.png', // 假定是 GitHub. 同时也可以是一个完整的 GitLab URL repo: "godbasin/vuepress-demo", // 自定义仓库链接文字。默认从 `themeConfig.repo` 中自动推断为 // "GitHub"/"GitLab"/"Bitbucket" 其中之一,或是 "Source"。 repoLabel: "Github", // 假如你的文档仓库和项目本身不在一个仓库: // docsRepo: 'vuejs/vuepress', // 假如文档不是放在仓库的根目录下: // 这里我们是放置在docs下的 docsDir: "docs", // 假如文档放在一个特定的分支下: // 这里我们放在一个叫sourcecode的分支下,因为master需要用来放置生成的静态文件 docsBranch: "sourcecode", // 顶部导航配置 nav: [ { text: "概述", link: "/" }, { text: "基础类文档", link: "/basic/" }, { text: "Vue类文档", link: "/vue/" } // 我们也可以添加FAQ的 // { text: 'FAQ', link: '/faq' } ], // 左侧导航菜单配置 sidebar: { "/basic/": [ { title: "基础类文档分类1", // 菜单名 collapsable: true, // 是否支持折叠菜单 children: ["/basic/1/basic-1-1.md", "/basic/1/basic-1-2.md"] }, { title: "基础类文档分类2", // 菜单名 collapsable: true, // 是否支持折叠菜单 children: ["/basic/2/basic-2-1.md", "/basic/2/basic-2-2.md"] } ], "/vue/": [ { title: "Vue类文档分类1", // 菜单名 collapsable: true, // 是否支持折叠菜单 children: ["/vue/1/vue-1-1.md", "/vue/1/vue-1-2.md"] }, { title: "Vue类文档分类2", // 菜单名 collapsable: true, // 是否支持折叠菜单 children: ["/vue/2/vue-2-1.md", "/vue/2/vue-2-2.md"] } ] } } };
(6) 启动项目。
配置完成后,我们可以使用npm run docs:dev
来启动本地环境,能看到环境搭建起来了:
图 15-1 本地环境启动
然后我们可以看到页面效果:
图 15-2 首页效果
图 15-3 Vue 类文档默认页效果
到这里,我们可以快速简单地将文档管理起来。
添加组件使用
接下来我们需要添加自己的组件,例如我想在首页中添加一个弹窗。
(1) 全局引入 Element。
这里我想要直接使用 Element 的弹窗样式,可以通过引入 Element 来直接使用,首先我们需要执行npm install element-ui
来安装 Element。同时,我们可以通过创建一个.vuepress/enhanceApp.js
文件来做一些应用级别的配置:
// docs/.vuepress/enhanceApp.js // 当该文件存在的时候,会被导入到应用内部 // 引入ElementUI import ElementUI from "element-ui"; // 全局引入样式 import "element-ui/lib/theme-chalk/index.css"; export default ({ Vue // VuePress 正在使用的 Vue 构造函数 }) => { try { // 使用element-ui Vue.use(ElementUI); } catch (e) { console.error(e.message); } };
到这里,我们已经全局引入了 ElementUI 库,接下来可以直接在文档中使用了。
(2) 在 Markdown 文档中使用 Vue 组件。
一般来说,所有在.vuepress/components
中找到的*.vue 文件将会自动地被注册为全局的异步组件,例如这里我们增加一个 Element 的弹窗:
<!-- docs/.vuepress/components/MyDialog.vue --> <!-- 这里直接使用Element官方弹窗的代码 --> <template> <el-button type="text" @click="open">点击打开 Message Box</el-button> </template> <script> export default { methods: { open() { this.$alert("这是一段内容", "标题名称", { confirmButtonText: "确定", callback: action => { this.$message({ type: "info", message: `action: ${action}` }); } }); } } }; </script>
然后我们可以直接使用这些组件在任意的 Markdown 文件中(组件名是通过文件名取到的),例如这里我们在首页中使用:
## <!-- docs/README.md --> home: true actionText: 快速阅读 → actionLink: /basic/1/basic-1-1.md features: - title: 基础类文档 details: 基础类文档描述。 - title: Vue 类文档 details: Vue 类文档描述。 - title: 其他补充 details: 其他补充描述。 footer: MIT Licensed | Copyright © 2018-present 被删 --- # Element 弹窗 <MyDialog/>
然后我们就可以看到效果:
图 15-4 首页效果
图 15-5 点击后出现弹窗
对于 VuePress,快速生成可用主题和配置是它的一大亮点,而直接在 Markdown 文件中使用 Vue 组件则是特别便利实用的另外一个特色。当然,VuePress 还支持自定义主题配置,不过这里篇幅关系就不多介绍,大家感兴趣可以去官网查看,也可以去https://github.com/godbasin/front-end-playground查看使用VuePress搭建的前端游乐场,源码在sourcecode分支。
2. Vue 生成 web 与小程序
如今,小程序用完即走、无需安装的便捷吸引了越来越多的用户愿意使用,同时微信提供的流量吸引了不少的小程序开发者加入其中。小程序有一套自己的规范,与常用的几大框架都不好进行兼容,我们来看一下为什么。
2.1 小程序与 Web 的区别
小程序的渲染层和逻辑层分别由两个线程管理:渲染层的界面使用了 WebView 进行渲染,逻辑层采用 JsCore 线程运行 JS 脚本。通过双线程的方式,我们可以阻止开发者使用一些浏览器提供的,诸如跳转页面、操作 DOM、动态执行脚本的开放性接口,来保证小程序的安全性,也方便平台进行管控。但是这样的设计也带来其他的问题,逻辑层和渲染层的通信(setData
)需要由 Native(微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发。以上这些情况意味着:
(1) 在浏览器中可以运行的 DOM、BOM 等对象和 API,都无法在小程序中使用。
(2) 小程序的一些 API 使用方式与浏览器不一致(请求、缓存等)。
对于强交互的场景(通信过多容易引起性能问题),小程序引入了原生组件,这样用户和原生组件的交互可以节省通信,从而提升性能。但这样还意味着:
(3) 在浏览器中可以使用的组件,在小程序中成了原生组件(input、video、canvas 等),使用方式和渲染效果完全不一致。
在这样的种种情况下,我们跑在浏览器中的代码,如果想要在小程序中运行,我们必须要重新开发来实现。那为什么一定要使用小程序呢,直接用 H5 不好吗?其实小程序做了很多的体验优化,同时天然的预加载、原生组件的流畅性,最重要的还是微信平台提供的流量,在很多情况下都不失为一个不错的选择。
2.2 开源类 Vue 小程序框架
虽然我们没法一套代码同时运行在浏览器和小程序中,但是依然有不少的开发者或者团队开发了一些框架,来尽可能使用一套代码完成多种环境的开发,例如 mpvue(Vue 系)、wepy(Vue 系)、taro(React 系)等。但毕竟不是官方支持,同时小程序的 API 和兼容性也不断在变动,使用的开源框架要是更新不及时,甚至可能成为技术债务。
2.3 kbone 的出现
kbone 作为一套解决方案应运而生,用于支持让一个 vue 项目可以同时在 web 端和小程序端被使用。前面说过,在小程序中无法直接使用 DOM/BOM 等 API,因此 kbone 提供了适配层的方式来进行兼容。适配层它提供基础的 DOM/BOM API,让小程序端尽量能使用 web 端的能力:
图 15-6 kbone 适配层
简单来说,就是提供了一个将 DOM/BOM 相关 API 转换成在小程序中的实现方式,这里有点像前面第13章中使用的配置方式,适配层维护一套虚拟 DOM 节点,然后根据节点信息,再通过简单的wx:for
和wx:if
来生成页面相关代码。
我们来看下,我们在第8章中的 Todo List 代码,直接使用 kbone 来运行,跑在 web 和小程序两端的效果是怎样的。
kbone 安装
使用 kbone,官方提供了三种方式。
(1) 新项目使用 kbone-cli。
对于新项目,可以使用 kbone-cli 来创建项目,首先需要全局安装:
# 全局安装 kbone-cli npm install -g kbone-cli
(2) 基于模板快速调整开发。
除了使用 kbone-cli 外,也可以直接将现有模板复制下来,然后在模板基础上进行开发改造。
(3) 自行改造 Webpacl 配置开发。
如果想要更灵活地搭建自己的项目,或者是想对已有的项目进行改造,则需要自己补充对应配置(构建到小程序代码的 webpack 配置、使用 webpack 构建中使用到的特殊插件 mp-webpack-plugin 配置)来实现 kbone 项目的构建。
Todo List 接入 kbone
其实针对已有的项目,不管是以上哪种方式都是可以的,这里我们就直接使用 kbone-cli 生成一个新项目,然后把原有的 Todo List 内容导入查看。
(1) 初始化项目。
首先执行kbone init kbone-todo-list
,生成一个初始化项目,初始化的时候需要选择对应的框架,这里我们选择 Vue:
图 15-7 kbone 初始化
初始化完成后,我们来看看目录说明:
<!-- 此模板 Web 端使用单入口,通过 vue-router + 动态 import 的方式来运行;小程序端则按照业务分拆成多个页面,同属一个业务的页面则通过 vue-router 来组织。 --> ├─ build │ ├─ miniprogram.config.js // mp-webpack-plugin 配置 │ ├─ webpack.base.config.js // Web 端构建基础配置 │ ├─ webpack.dev.config.js // Web 端构建开发环境配置 │ ├─ webpack.mp.config.js // 小程序端构建配置 │ └─ webpack.prod.config.js // Web 端构建生产环境配置 ├─ dist │ ├─ mp // 小程序端目标代码目录,使用微信开发者工具打开,用于生产环境 │ └─ web // web 端编译出的文件,用于生产环境 ├─ src │ ├─ common // 通用组件 │ ├─ mp // 小程序端入口目录 │ │ ├─ home // 小程序端 home 页面 │ │ │ └─ main.mp.js // 小程序端入口文件 │ │ └─ other // 小程序端 other 页面 │ │ └─ main.mp.js // 小程序端入口文件 │ ├─ detail // detail 页面 │ ├─ home // home 页面 │ ├─ list // list 页面 │ ├─ router // vue-router 路由定义 │ ├─ store // vuex 相关目录 │ ├─ App.vue // Web 端入口主视图 │ └─ main.js // Web 端入口文件 └─ index.html // Web 端入口模板
(2) 迁移 Todo List 代码。
初始化 kbone 项目之后,我们需要将原有的代码迁移过来,迁移过程中有以下注意事项:
- https 引入的 css/js 资源在小程序中不再可用,可以下载下来通过相对路径引入
- scoped 样式在小程序中不可用,需要自行加作用域或是进行冲突解决
- 部分样式在 Web 端和小程序端表现不一致,需要进行调整
- Web 端的鼠标 hover、dbclick 等状态和事件在小程序中不再可用,需要进行调整
- 之前全局引入了 Velocity 进行延时动画,在小程序中需要移除
- 路由调整,需要同时调整
src/router/index.js
文件、src/mp/todo/main.mp.js
文件、build/miniprogram.config.js
文件、build/webpack.mp.config.js
(3) Web 端启动。
代码迁移过程比较琐碎,这里就不详细讲啦,大家可以去找源码进行参考。迁移完之后,我们首先将 Web 端跑起来,需要执行npm run web
命令之后,我们来看看效果:
图 15-8 Web 端启动效果
我们能看到主要包括两个变动:
(1) 增加添加按钮,因为在小程序端无法监控@keyup.enter
事件。
(2) 删除图标,从之前需要鼠标 hover 可见,调整成直接可见,因为在小程序中没有 hover 状态。
点击删除的时候,会进行弹窗,这里使用的是 Vuex 进行状态更新(参考第11章) :
图 15-9 点击删除弹窗效果
(4) 小程序端启动。
在小程序端启动,要先执行npm run mp
命令,接下来还需要先进入 dist/mp 目录执行npm install
安装相关的依赖包(主要是 miniprogram-render 和 miniprogram-element),然后用开发者工具打开 dist/mp 目录后再进行 npm 构建(菜单栏-工具-构建 npm):
图 15-10 工具中效果
我们能看到除了样式有些不一致之外,其他功能都是可用的。另外,我们从工具中可以看到,最终生成的代码基本上是通过<element>
组件来实现的,我们看看生成的代码:
<!-- dist/mp/pages/todo/index.html --> <element wx:if="{{pageId}}" class="{{bodyClass}}" style="{{bodyStyle}}" data-private-node-id="e-body" data-private-page-id="{{pageId}}" > </element>
// dist/mp/pages/todo/index.json // 这里使用了官方兼容层组件miniprogram-element { "enablePullDownRefresh": false, "usingComponents": { "element": "miniprogram-element" } }
如果要继续看下去,你会发现 dist/mp/pages/todo/index.js 文件中也是很多兼容性的代码,也可以验证了我们前面说过的,适配层维护一套虚拟 DOM 节点信息,再通过简单的wx:for
和wx:if
配合 miniprogram-element 中的 element 组件来生成页面相关代码。
点击删除的时候,Vuex 状态相关也是可以正常执行的:
图 15-11 手机执行效果
当然,kbone 也会存在一些问题,官方也进行了相关的说明,常见的例如:
- 小程序里的所有页面必须同源
- 受限于小程序环境,目前无法支持异步组件
- 小程序不支持属性选择器,所以无法支持 scoped style
- iframe 标签无法支持
- vue 的 transition 组件无法完美支持
- 不可使用 rem
- 等等
关于 kbone 相关的暂时就介绍到这里,其实我们的 Todo List 样式是 PC 端适应的,而如果做了移动端的样式兼容,就可以很方便地使用 kbone 同构生成 Web 代码(移动端+PC)和小程序代码了,而小程序官方的微信开放社区也正是这样做的,一套代码维护多端。
3. 其他 Vue 周边
除了 VuePress 和 kbone 之外,常用的还有 Nuxt.js。
Nuxt.js 是一个基于 Vue(Vue.js、Vue Router、Vuex 等)、Webpack 和 Babel 的通用应用框架,它预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置,开发中可以直接基于初始化的项目上进行快速开发。使用服务器端渲染,最主要其实就是为了解决 SEO 的问题,同时服务器端渲染还能解决的首屏加载速度的问题。Nuxt.js 为"客户端/服务端"这种典型的应用架构模式提供了许多有用的特性,包括强大的路由功能、异步数据加载、中间件支持、布局支持等。当然,除了服务端渲染,Nuxt.js 同时还支持单页应用(SPA)、生成静态站点等模式。
其实我们前面也介绍过 Vuex、Vue CLI 等,另外 Vue 还包括了 Vue Loader、vue-devtools 等工具,由于篇幅关系这里不介绍使用,大家可以去官网上学习下怎样使用。Vue 作为如今国内的主流框架之一,提供了很完备的生态和社区,越来越多的开发者也加入进来一起建设,周边拓展可见也会越来越丰富。