有没有vue-vuex router sync完整实例

原文& http://jiongks.name/blog/just-vue/
最近在内部项目中做了一些基于 vue + webpack 的尝试,在小范围和同事们探讨之后,还是蛮多同学认可和喜欢的,所以通过 blog 分享给更多人。
首先,我会先简单介绍一下 vue 和 webpack:
(当然如果你已经比较熟悉它们的话前两个部分可以直接跳过)
Vue.js 是一款极简的 mvvm 框架,如果让我用一个词来形容它,就是 “轻&巧” 。如果用一句话来描述它,它能够集众多优秀逐流的前端框架之大成,但同时保持简单易用。废话不多说,来看几个例子:
&script src=&vue.js&&&/script&
&div id=&demo&&
{{message}}
&input v-model=&message&&
var vm = new Vue({
el: '#demo',
message: 'Hello Vue.js!'
首先,代码分两部分,一部分是 html,同时也是视图模板,里面包含一个值为message的文本何一个相同值的输入框;另一部分是 script,它创建了一个 vm 对象,其中绑定的 dom 结点是#demo,绑定的数据是{message: 'Hello Vue.js'},最终页面的显示效果就是一段Hello Vue.js文本加一个含相同文字的输入框,更关键的是,由于数据是双向绑定的,所以我们修改文本框内文本的同时,第一段文本和被绑定的数据的message字段的值都会同步更新??而这底层的复杂逻辑,Vue.js 已经全部帮你做好了。
再多介绍一点
我们还可以加入更多的 directive,比如:
&script src=&vue.js&&&/script&
&div id=&demo2&&
&img title=&{{name}}& alt=&{{name}}& v-attr=&src: url&&
&input v-model=&name&&
&input v-model=&url&&
var vm = new Vue({
el: '#demo',
name: 'taobao',
url: '/favicon.ico'
这里的视图模板加入了一个&img&标签,同时我们看到了 2 个特性的值都写作了{{name}}。这样的话,图片的title和alt特性值就都会被绑定为字符串'taobao'。
如果想绑定的特性是像img[src]这样的不能在 html 中随意初始化的 (可能默认会产生预期外的网络请求),没关系,有v-attr=&src: url&这样的写法,把被绑定的数据里的url同步过来。
没有介绍到的功能还有很多,推荐大家来我(发起并)翻译的 Vue.js 中文文档
web 组件化
最后要介绍 Vue.js 对于 web 组件化开发的思考和设计
如果我们要开发更大型的网页或 web 应用,web 组件化的思维是非常重要的,这也是今天整个前端社区长久不衰的话题。
Vue.js 设计了一个*.vue格式的文件,令每一个组件的样式、模板和脚本集合成了一整个文件, 每个文件就是一个组件,同时还包含了组件之间的依赖关系,麻雀虽小五脏俱全,整个组件从外观到结构到特性再到依赖关系都一览无余 :
并且支持预编译各种方言:
这样再大的系统、在复杂的界面,也可以用这样的方式庖丁解牛。当然这种组件的写法是需要编译工具才能最终在浏览器端工作的,下面会提到一个基于 webpack 的具体方案。
从功能角度,template, directive, data-binding, components 各种实用功能都齐全,而 filter, computed var, var watcher, custom event 这样的高级功能也都洋溢着作者的巧思;从开发体验角度,这些设计几乎是完全自然的,没有刻意设计过或欠考虑的感觉,只有个别不得已的地方带了自己框架专属的v-前缀。从性能、体积角度评估,Vue.js 也非常有竞争力!
介绍 webpack
webpack 是另一个近期发现的好东西。它主要的用途是通过 CommonJS 的语法把所有浏览器端需要发布的静态资源做相应的准备,比如资源的合并和打包。
举个例子,现在有个脚本主文件app.js依赖了另一个脚本module.js
var module = require('./module.js')
... module.x ...
// module.js
exports.x = ...
则通过webpack app.js bundle.js命令,可以把app.js和module.js打包在一起并保存到bundle.js
同时 webpack 提供了强大的 loader 机制和 plugin 机制,loader 机制支持载入各种各样的静态资源,不只是 js 脚本、连 html, css, images 等各种资源都有相应的 loader 来做依赖管理和打包;而 plugin 则可以对整个 webpack 的流程进行一定的控制。
比如在安装并配置了 css-loader 和 style-loader 之后,就可以通过require('./bootstrap.css')这样的方式给网页载入一份样式表。非常方便。
webpack 背后的原理其实就是把所有的非 js 资源都转换成 js (如把一个 css 文件转换成“创建一个style标签并把它插入document”的脚本、把图片转换成一个图片地址的 js 变量或 base64 编码等),然后用 CommonJS 的机制管理起来。一开始对于这种技术形态我个人还是不太喜欢的,不过随着不断的实践和体验,也逐渐习惯并认同了。
最后,对于之前提到的 Vue.js,作者也提供了一个叫做 vue-loader 的 npm 包 ,可以把*.vue文件转换成 webpack 包,和整个打包过程融合起来。所以有了 Vue.js、webpack 和 vue-loader,我们自然就可以把它们组合在一起试试看!
项目实践流程
回到正题。今天要分享的是,是基于上面两个东西:Vue.js 和 webpack,以及把它们串联起来的 vue-loader
Vue.js 的作者以及提供了一个基于它们三者的 项目示例 。而我们的例子会更贴近实际工作的场景,同时和团队之前总结出来的项目特点和项目流程相吻合。
目录结构设计
&components&组件目录,一个组件一个.vue文件
&lib&如果实在有不能算组件,但也不来自外部 (tnpm) 的代码,可以放在这里
&src&主应用/页面相关文件
app.html主 html
app.vue主 vue
app.js通常做的事情只是var Vue = require('vue'); new Vue(require('./app.vue'))
&dist&(ignored)
&node_modules&(ignored)
gulpfile.js设计项目打包/监听等任务
package.json记录项目基本信息,包括模块依赖关系
README.md项目基本介绍
通过gulpfile.js我们可以设计整套基于 webpack 的打包/监听/调试的任务
在 gulp-webpack 包的官方文档里推荐的写法是这样的:
var gulp = require('gulp');
var webpack = require('gulp-webpack');
var named = require('vinyl-named');
gulp.task('default', function() {
return gulp.src(['src/app.js', 'test/test.js'])
.pipe(named())
.pipe(webpack())
.pipe(gulp.dest('dist/'));
我们对这个文件稍加修改,首先加入 vue-loader
tnpm install vue-loader --save
.pipe(webpack({
loaders: [
{ test: /\.vue$/, loader: 'vue'}
其次,把要打包的文件列表从gulp.src(...)中抽出来,方便将来维护,也有机会把这个信息共享到别的任务
var appList = ['main', 'sub1', 'sub2']
gulp.task('default', function() {
return gulp.src(mapFiles(appList, 'js'))
* @private
function mapFiles(list, extname) {
return list.map(function (app) {return 'src/' + app + '.' + extname})
现在运行gulp命令,相应的文件应该就打包好并生成在了dist目录下。然后我们在src/*.html中加入对这些生成好的js文件的引入:
&!DOCTYPE html&
&meta charset=&utf-8&&
&title&Main&/title&
&div id=&app&&&/div&
&script src=&../dist/main.js&&&/script&
用浏览器打开src/main.html这时页面已经可以正常工作了
监听更加简单,只要在刚才webpack(opt)的参数中加入watch: true就可以了。
.pipe(webpack({
loaders: [
{ test: /\.vue$/, loader: 'vue'}
watch: true
当然最好把打包和监听设计成两个任务,分别起名为bundle和watch:
gulp.task('bundle', function() {
return gulp.src(mapFiles(appList, 'js'))
.pipe(named())
.pipe(webpack(getConfig()))
.pipe(gulp.dest('dist/'))
gulp.task('watch', function() {
return gulp.src(mapFiles(appList, 'js'))
.pipe(named())
.pipe(webpack(getConfig({watch: true})))
.pipe(gulp.dest('dist/'))
* @private
function getConfig(opt) {
var config = {
loaders: [
{ test: /\.vue$/, loader: 'vue'}
if (!opt) {
return config
for (var i in opt) {
config[i] = opt
return config
现在你可以不必每次修改文件之后都运行gulp bundle才能看到最新的效果,每次改动之后直接刷新浏览器即可。
打包好的代码已经不那么易读了,直接在这样的代码上调试还是不那么方便的。这个时候,webpack + vue 有另外一个现成的东西:source map 支持。为 webpack 加入这个配置字段devtool: 'source-map':
var config = { module: { loaders: [ { test: /.vue$/, loader: 'vue'} ] }, devtool: 'source-map' }
再次运行gulp bundle或gulp watch试试看,是不是开发者工具里 debug 的时候,可以追踪断点到源代码了呢:)
完整的 javascript 代码如下:
var gulp = require('gulp')
var webpack = require('gulp-webpack')
var named = require('vinyl-named')
var appList = ['main']
gulp.task('default', ['bundle'], function() {
console.log('done')
gulp.task('bundle', function() {
return gulp.src(mapFiles(appList, 'js'))
.pipe(named())
.pipe(webpack(getConfig()))
.pipe(gulp.dest('dist/'))
gulp.task('watch', function() {
return gulp.src(mapFiles(appList, 'js'))
.pipe(named())
.pipe(webpack(getConfig({watch: true})))
.pipe(gulp.dest('dist/'))
* @private
function getConfig(opt) {
var config = {
loaders: [
{ test: /\.vue$/, loader: 'vue'}
devtool: 'source-map'
if (!opt) {
return config
for (var i in opt) {
config[i] = opt
return config
* @private
function mapFiles(list, extname) {
return list.map(function (app) {return 'src/' + app + '.' + extname})
最后,杜拉拉不如紫罗兰
做出一个 vue + webpack 的 generator,把这样的项目体验分享给更多的人。目前我基于团队内部在使用的轻量级脚手架工具写了一份名叫just-vue的 generator,目前这个 generator 还在小范围试用当中,待比较成熟之后,再分享出来
其实上面提到的just-vue脚手架已经远不止文章中介绍的东西了, 我们在业务落地的“最后一公里”做了更多的沉淀和积累,比如自动图片上传与画质处理、rem单位自动换算、服务端/客户端/数据埋点接口的梳理与整合、自动化 htmlone 打包与 awp 发布等等。它们为支持业务的开发者提供了更简单高效的工作体验。 篇幅有限,更多内容我也希望将来有机会再多分享出来。
最后再次希望大家如果有兴趣的话可以来玩一下,无线前端组内的同学我都愿意提供一对一入门指导:)
Just Vue!基于 Webpack & Vue & Vue-Router 的 SPA 初体验_腾讯Bugly_【传送门】
基于 Webpack & Vue & Vue-Router 的 SPA 初体验
最近这几年的前端圈子,由于戏台一般精彩纷呈,从 MVC 到 MVVM,你刚唱罢我登场。 backbone,angularjs 已成昨日黄花,reactjs 如日中天,同时另一更轻量的 vue 发展势头更猛,尤其是即将 release 的2.0版本,号称兼具了 angularjs 和 reactjs 的两者优点。不过现在的官方版本还是1.0 ,下面就是基于1.0版本的初体验。1. 为什么要 SPA?SPA: 就是俗称的单页应用(Single Page Web Application)。在移动端,特别是 hybrid 方式的H5应用中,性能问题一直是痛点。 使用 SPA,没有页面切换,就没有白屏阻塞,可以大大提高 H5 的性能,达到接近原生的流畅体验。2. 为什么选择 vue?在选择 vue 之前,使用 reactjs 也做过一个小 Demo,虽然两者都是面向组件的开发思路,但是 reactjs 的全家桶方式,实在太过强势,而自己定义的 JSX 规范,揉和在 JS 的组件框架里,导致如果后期发生页面改版工作,工作量将会巨大。vue 相对来说,就轻量的多,他的view层,还是原来的 dom 结构,除了一些自定义的 vue 指令作为自定义标签以外,只要学会写组件就可以了,学习成本也比较低。3. 环境配置初始化工程,需要 node 环境使用 npm 安装相应的依赖包。先创建一个测试目录,在里面依次输入以下命令。//初始化package.json
//安装vue的依赖
npm install vue --save
npm install vue-router --save
//安装webpack的开发依赖
npm install webpack --save-dev
//安装babel的ES6 Loader 的开发依赖
npm install babel --save-dev
npm install babel-core --save-dev
npm install babel-loader --save-dev
npm install babel-preset-es2015 --save-dev
//安装html loacer 的开发依赖
npm install html-loader --save-dev4. 目录结构src 为开发目录,其中 components 为组件子目录,templates 为模板子目录。dist 为构建出的文件目录。index.html 为入口文件。package.json 为项目描述文件,是刚才 npm init 所建立。webpack.config.js 是 webpack 的构建配置文件5. Webpack 配置下面是 webpack 的配置文件,如何使用 webpack,请移步 webpack 的官网。var webpack= require("webpack");
module.exports={
bundle:[ "./src/app.js"]
path:__dirname,
publicPath:"/",
filename:"dist/[name].js"
{test: /\.html$/, loaders: ['html']},
{test: /(\.js)$/, loader:["babel"] ,exclude:/node_modules/,
presets:["es2015"]
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}6. 入口文件index.html
浏览器里试试看:子组件成功被调用了11. 组件跳转传参组件之间的跳转传参,也是一种非常常见的情况。下面为列表页,增加跳转到详情页的跳转,并传参 id 给详情页修改路由 routes.jsmodule.exports = {
component: require('./components/index')
'/list': {
component: require('./components/list')
//增加详情页的跳转路由,并在路径上加上id传参,具名为name:show
'/show/:id': {
name:"show",
component: require('./components/show')
component: require('./components/notFound')
}添加组件 showcomponents/show.jsmodule.exports = {
template: require('../templates/show.html'),
data:function(){
return {};
created:function(){
//获取params的参数ID
var id=this.$route.params.
//根据获取的参数ID,返回不同的data对象(真实业务中,这里应该是Ajax获取数据)
if (id==1){
this.$data={"id":id,"name":"hello111","age":24};
this.$data={"id":id,"name":"hello222","age":28};
ready: function () {
console.log(this.$data);
};templates/show.htmlShow
Hello show page!
name:${name}
age:${age}修改 templates/item.html我是subitem:
这里 name:’show’ 表示具名路由路径,params 就是传参。继续浏览器里点到详情页试试:点击“hello11”,跳转到详情页:传参逻辑成功。12. 嵌套路由仅有路由跳转是远远不够的,很多情况下,我们还有同一个页面上,多标签页的切换,在 vue 中,用嵌套路由,也可以非常方便的实现。添加两个小组件components/tab1.jsmodule.exports = {
template: "Tab1 content"
};components/tab2.jsmodule.exports = {
template: "Tab2 content"
};修改 components/index.js 组件,挂载这两个子组件import tab1 from "./tab1";
import tab2 from "./tab2";
module.exports = {
template: require('../templates/index.html'),
components:{
"tab1":tab1,
"tab2":tab2
ready: function () {
};在路由里加上子路由module.exports = {
component: require('./components/index'),
subRoutes:{
component:require('./components/tab1')
component:require('./components/tab2')
'/list': {
component: require('./components/list')
'/show/:id': {
name:"show",
component: require('./components/show')
component: require('./components/notFound')
}好了,在浏览器里试一下:初始状态:点了 tab1,tab2:Tab 切换没问题,可是,初始状态显示是空的,能不能默认显示 Tab1 Content 呢?很简单,调整下路由就可以了:module.exports = {
component: require('./components/index'),
subRoutes:{
//默认显示Tab1
component:require('./components/tab1')
component:require('./components/tab1')
component:require('./components/tab2')
}13. 业界 vue 使用案例小米移动官网:/1/#/index 饿了吗招聘:https://jobs-mobile.ele.me/#!/(复制后在浏览器中打开)如果您觉得我们的内容还不错,就请扫描二维码赞赏作者并转发到朋友圈,和小伙伴一起分享吧~本文系腾讯Bugly独家内容,转载请在文章开头显眼处注明作者和出处“腾讯Bugly()”
觉得不错,分享给更多人看到
腾讯Bugly 微信二维码
分享这篇文章
9月10日 0:45
腾讯Bugly 最新文章
腾讯Bugly 热门文章Vue.js――vue-router 60分钟快速入门 - keepfool
来源:互联网
编辑:刘梓楠
有网友碰到过这样的问题:Vue.js――vue-router 60分钟快速入门 - keepfool,问题详细内容为:挺不错的博文:Vue.js――vue-router 60分钟快速入门 - keepfool,我搜你通过互联网收集了相关的一些解决方案,希望对有过相同或者相似问题的网友提供帮助,具体如下:
vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。
本文将以示例的形式来介绍vue-router的各个特性,一共包含6个示例,每个示例都有乞丐版,前5个示例有皇帝版。乞丐版是将所有代码混杂在一起的HTML页面,皇帝版是基于vue-webpack-simple模板构建的。
乞丐版可以让你快速地了解到vue-router的一些特性和API;皇帝版则基于.vue组件和单独的路由配置,更适用于实际的应用。
本文的Demo和源代码已放到GitHub,如果您觉得内容不错,请点个赞,或在GitHub上加个星星!
第一个单页面应用 嵌套路由示例 具名路径示例 路由对象示例 让链接处于选中状态示例 钩子函数示例 GitHub Source
在GitHub上,乞丐版和皇帝版的目录结构如下:
├─06.Router
// vue-router示例目录
// 乞丐版示例
├──basic_01.html // 第一个单页面应用
├──basic_02.html // 嵌套路由示例
├──basic_03.html // 具名路径示例
├──basic_04.html // 路由对象实例
├──basic_05.html // 让链接处于选中状态示例
├──basic_06.html // 钩子函数示例
├─demo01
// 皇帝版,和basic_01.html对应
├─demo02
// 皇帝版,和basic_02.html对应
├─demo03
// 皇帝版,和basic_03.html对应
├─demo04
// 皇帝版,和basic_04.html对应
├─demo05
// 皇帝版,和basic_05.html对应
第一个单页面应用(01)
现在我们以一个简单的单页面应用开启vue-router之旅,这个单页面应用有两个路径:/home和/about,与这两个路径对应的是两个组件Home和About。
1. 创建组件
首先引入vue.js和vue-router.js:
&script src="js/vue.js"&&/script&
&script src="js/vue-router.js"&&/script&
然后创建两个组件构造器Home和About:
var Home = Vue.extend({
template: '&div&&h1&Home&/h1&&p&{{msg}}&/p&&/div&',
data: function() {
msg: 'Hello, vue router!'
var About = Vue.extend({
template: '&div&&h1&About&/h1&&p&This is the tutorial about vue-router.&/p&&/div&'
2. 创建Router
var router = new VueRouter()
调用构造器VueRouter,创建一个路由器实例router。
3. 映射路由
router.map({
'/home': { component: Home },
'/about': { component: About }
调用router的map方法映射路由,每条路由以key-value的形式存在,key是路径,value是组件。例如:'/home'是一条路由的key,它表示路径;{component: Home}则表示该条路由映射的组件。
4. 使用v-link指令
&div class="list-group"&
&a class="list-group-item" v-link="{ path: '/home'}"&Home&/a&
&a class="list-group-item" v-link="{ path: '/about'}"&About&/a&
在a元素上使用v-link指令跳转到指定路径。
5. 使用&router-view&标签
&router-view&&/router-view&
在页面上使用&router-view&&/router-view&标签,它用于渲染匹配的组件。
6. 启动路由
var App = Vue.extend({})
router.start(App, '#app')
路由器的运行需要一个根组件,router.start(App, '#app') 表示router会创建一个App实例,并且挂载到#app元素。注意:使用vue-router的应用,不需要显式地创建Vue实例,而是调用start方法将根组件挂载到某个元素。
当你从GitHub上获取到最新的源代码后,如果想运行皇帝版,以demo01为例,在Git Bash下执行以下命令:
npm run demo01-dev
然后在浏览器中访问地址http://127.0.0.1:8080
如果要编译和发布,请在Git Bash下执行以下命令:
npm run demo01-build
编写单页面的步骤
上面的6个步骤,可以说是创建一个单页面应用的基本步骤:
JavaScript
创建组件:创建单页面应用需要渲染的组件
创建路由:创建VueRouter实例
映射路由:调用VueRouter实例的map方法
启动路由:调用VueRouter实例的start方法
使用v-link指令
使用&router-view&标签
router.redirect
应用在首次运行时右侧是一片空白,应用通常都会有一个首页,例如:Home页。使用router.redirect方法将根路径重定向到/home路径:
router.redirect({
'/': '/home'
router.redirect方法用于为路由器定义全局的重定向规则,全局的重定向会在匹配当前路径之前执行。
当用户点击v-link指令元素时,我们可以大致猜想一下这中间发生了什么事情:
vue-router首先会去查找v-link指令的路由映射
然后根据路由映射找到匹配的组件
最后将组件渲染到&router-view&标签
嵌套路由(02)
嵌套路由是个常见的需求,假设用户能够通过路径/home/news和/home/message访问一些内容,一个路径映射一个组件,访问这两个路径也会分别渲染两个组件。
实现嵌套路由有两个要点:
在组件内部使用&router-view&标签
在路由器对象中给组件定义子路由
现在我们就动手实现这个需求。
组件模板:
&template id="home"&
&h1&Home&/h1&
&p&{{msg}}&/p&
&ul class="nav nav-tabs"&
&a v-link="{ path: '/home/news'}"&News&/a&
&a v-link="{ path: '/home/message'}"&Messages&/a&
&router-view&&/router-view&
&/template&
&template id="news"&
&li&News 01&/li&
&li&News 02&/li&
&li&News 03&/li&
&/template&
&template id="message"&
&li&Message 01&/li&
&li&Message 02&/li&
&li&Message 03&/li&
&/template&
组件构造器:
var Home = Vue.extend({
template: '#home',
data: function() {
msg: 'Hello, vue router!'
var News = Vue.extend({
template: '#news'
var Message = Vue.extend({
template: '#message'
路由映射:
router.map({
'/home': {
component: Home,
// 定义子路由
subRoutes: {
'/news': {
component: News
'/message': {
component: Message
'/about': {
component: About
在/home路由下定义了一个subRoutes选项,/news和/message是两条子路由,它们分别表示路径/home/news和/home/message,这两条路由分别映射组件News和Message。
该示例运行如下:
注意:这里有一个概念要区分一下,/home/news和/home/message是/home路由的子路由,与之对应的News和Message组件并不是Home的子组件。
具名路径(03)
在有些情况下,给一条路径加上一个名字能够让我们更方便地进行路径的跳转,尤其是在路径较长的时候。
我们再追加一个组件NewsDetail,该组件在访问/home/news/detail路径时被渲染,组件模板:
&template id="newsDetail"&
News Detail - {{$route.params.id}} ......
&/template&
组件构造器:
var NewsDetail = Vue.extend({
template: '#newsDetail'
具名路由映射
router.map({
'/home': {
component: Home,
subRoutes: {
'/news': {
name: 'news',
component: News,
subRoutes: {
'detail/:id': {
name: 'detail',
component: NewsDetail
'/message': {
component: Message
'/about': {
component: About
注意:我们在定义/homes/news/和home/news/detail/:id路由时,给该路由指定了name属性。/:id是路由参数,例如:如果要查看id = '01'的News详情,那么访问路径是/home/news/detail/01。
Home组件和News组件模板:
&template id="home"&
&h1&Home&/h1&
&p&{{msg}}&/p&
&ul class="nav nav-tabs"&
&a v-link="{ name: 'news'}"&News&/a&
&a v-link="{ path: '/home/message'}"&Messages&/a&
&router-view&&/router-view&
&/template&
&template id="news"&
&a v-link="{ name: 'detail', params: {id: '01'} }"&News 01&/a&
&a v-link="{ path: '/home/news/detail/02'}"&News 02&/a&
&a v-link="{ path: '/home/news/detail/03'}"&News 03&/a&
&router-view&&/router-view&
&/template&
&a v-link="{ name: 'news'}"&News&/a&和&a v-link="{ name: 'detail', params: {id: '01'} }"&News 01&/a&这两行HTML代码,使用了用了具名路径。
该示例运行如下:
v-link指令
用了这么久的v-link指令,是该介绍一下它了。
v-link 是一个用来让用户在 vue-router 应用的不同路径间跳转的指令。该指令接受一个 JavaScript 表达式,并会在用户点击元素时用该表达式的值去调用 router.go。
具体来讲,v-link有三种用法:
&!-- 字面量路径 --&
&a v-link="'home'"&Home&/a&
&!-- 效果同上 --&
&a v-link="{ path: 'home' }"&Home&/a&
&!-- 具名路径 --&
&a v-link="{ name: 'detail', params: {id: '01'} }"&Home&/a&
v-link 会自动设置 &a& 的 href 属性,你无需使用href来处理浏览器的调整,原因如下:
它在 HTML5 history 模式和 hash 模式下的工作方式相同,所以如果你决定改变模式,或者 IE9 浏览器退化为 hash 模式时,都不需要做任何改变。
在 HTML5 history 模式下,v-link 会监听点击事件,防止浏览器尝试重新加载页面。
在 HTML5 history 模式下使用 root 选项时,不需要在 v-link 的 URL 中包含 root 路径。
路由对象(04)
在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route ,并且当路由切换时,路由对象会被更新。
路由对象暴露了以下属性:
$route.path 字符串,等于当前路由对象的路径,会被解析为绝对路径,如 "/home/news" 。
$route.params
对象,包含路由中的动态片段和全匹配片段的键值对
$route.query
对象,包含路由中查询参数的键值对。例如,对于 /home/news/detail/01?favorite=yes ,会得到 $route.query.favorite == 'yes' 。
$route.router
路由规则所属的路由器(以及其所属的组件)。
$route.matched
数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
$route.name
当前路径的名字,如果没有使用具名路径,则名字为空。
在页面上添加以下代码,可以显示这些路由对象的属性:
&p&当前路径:{{$route.path}}&/p&
&p&当前参数:{{$route.params | json}}&/p&
&p&路由名称:{{$route.name}}&/p&
&p&路由查询参数:{{$route.query | json}}&/p&
&p&路由匹配项:{{$route.matched | json}}&/p&
$route.path, $route.params, $route.name, $route.query这几个属性很容易理解,看示例就能知道它们代表的含义。
(由于$route.matched内容较长,所以没有将其显示在画面上)
这里我要稍微说一下$router.matched属性,它是一个包含性的匹配,它会将嵌套它的父路由都匹配出来。
例如,/home/news/detail/:id这条路径,它包含3条匹配的路由:
/home/news/detail/:id
/home/news
另外,带有 v-link 指令的元素,如果 v-link 对应的 URL 匹配当前的路径,该元素会被添加特定的class,该class的默认名称为v-link-active。例如,当我们访问/home/news/detail/03这个URL时,根据匹配规则,会有3个链接被添加v-link-active。
让链接处于活跃状态(05)
以上画面存在两个问题:
当用户点击Home链接或About链接后,链接没有显示为选中
当用户点击News或Message链接后,链接没有显示为选中
设置activeClass
第1个问题,可以通过设定v-link指令的activeClass解决。
&a class="list-group-item" v-link="{ path: '/home', activeClass: 'active'}"&Home&/a&
&a class="list-group-item" v-link="{ path: '/about', activeClass: 'active'}"&About&/a&
设定了v-link指令的activeClass属性后,默认的v-link-active被新的class取代。
第2个问题,为v-link指令设定activeClass是不起作用的,因为我们使用的是bootstrap的样式,需要设置a标签的父元素&li&才能让链接看起来处于选中状态,就像下面的代码所展现的:
&ul class="nav nav-tabs"&
&li class="active"&
&a v-link="{ path: '/home/news'}"&News&/a&
&a v-link="{ path: '/home/message'}"&Messages&/a&
如何实现这个效果呢?你可能会想到,为Home组件的data选项追加一个currentPath属性,然后使用以下方式绑定class。
&ul class="nav nav-tabs"&
&li :class="currentPath == '/home/news' ? 'active': ''"&
&a v-link="{ path: '/home/news'}"&News&/a&
&li :class="currentPath == '/home/message' ? 'active': ''"&
&a v-link="{ path: '/home/message'}"&Messages&/a&
现在又出现了另一个问题,在什么情况下给currentPath赋值呢?
用户点击v-link的元素时,是路由的切换。每个组件都有一个route选项,route选项有一系列钩子函数,在切换路由时会执行这些钩子函数。其中一个钩子函数是data钩子函数,它用于加载和设置组件的数据。
var Home = Vue.extend({
template: '#home',
data: function() {
msg: 'Hello, vue router!',
currentPath: ''
data: function(transition){
transition.next({
currentPath: transition.to.path
该示例运行效果如下:
钩子函数(06)
路由的切换过程,本质上是执行一系列路由钩子函数,钩子函数总体上分为两大类:
全局的钩子函数
组件的钩子函数
全局的钩子函数定义在全局的路由对象中,组件的钩子函数则定义在组件的route选项中。
全局钩子函数
全局钩子函数有2个:
beforeEach:在路由切换开始时调用
afterEach:在每次路由切换成功进入激活阶段时被调用
组件的钩子函数
组件的钩子函数一共6个:
data:可以设置组件的data
activate:激活组件
deactivate:禁用组件
canActivate:组件是否可以被激活
canDeactivate:组件是否可以被禁用
canReuse:组件是否可以被重用
每个切换钩子函数都会接受一个 transition 对象作为参数。这个切换对象包含以下函数和方法:
transition.to 表示将要切换到的路径的路由对象。
transition.from
代表当前路径的路由对象。
transition.next()
调用此函数处理切换过程的下一步。
transition.abort([reason])
调用此函数来终止或者拒绝此次切换。
transition.redirect(path)
取消当前切换并重定向到另一个路由。
钩子函数的执行顺序
全局钩子函数和组件钩子函数加起来一共8个,为了熟练vue router的使用,有必要了解这些钩子函数的执行顺序。
为了直观地了解这些钩子函数的执行顺序,在画面上追加一个Vue实例:
var well = new Vue({
el: '.well',
color: '#ff0000'
methods: {
setColor: function(){
this.color = '#' + parseInt(Math.random()*256).toString(16)
+ parseInt(Math.random()*256).toString(16)
+ parseInt(Math.random()*256).toString(16)
setColoredMessage: function(msg){
this.msg +=
'&p style="color: ' + this.color + '"&' + msg + '&/p&'
setTitle: function(title){
this.msg =
'&h2 style="color: #333"&' + title + '&/h2&'
well实例的HTML:
&div class="well"&
{{{ msg }}}
然后,添加一个RouteHelper函数,用于记录各个钩子函数的执行日志:
function RouteHelper(name) {
var route = {
canReuse: function(transition) {
well.setColoredMessage('执行组件' + name + '的钩子函数:canReuse')
return true
canActivate: function(transition) {
well.setColoredMessage('执行组件' + name + '的钩子函数:canActivate')
transition.next()
activate: function(transition) {
well.setColoredMessage('执行组件' + name + '的钩子函数:activate')
transition.next()
canDeactivate: function(transition) {
well.setColoredMessage('执行组件' + name + '的钩子函数:canDeactivate')
transition.next()
deactivate: function(transition) {
well.setColoredMessage('执行组件' + name + '的钩子函数:deactivate')
transition.next()
data: function(transition) {
well.setColoredMessage('执行组件' + name + '的钩子函数:data')
transition.next()
最后,将这些钩子函数应用于各个组件:
var Home = Vue.extend({
template: '#home',
data: function() {
msg: 'Hello, vue router!',
route: RouteHelper('Home')
var News = Vue.extend({
template: '#news',
route: RouteHelper('News')
var Message = Vue.extend({
template: '#message',
route: RouteHelper('Message')
var About = Vue.extend({
template: '#about',
route: RouteHelper('About')
我们按照以下步骤做个小实验:
运行应用(访问/home路径)
访问/home/news路径
访问/home/message路径
访问/about路径
切换控制流水线
当用户点击了/home/news链接,然后再点击/home/message链接后,vue-router做了什么事情呢?它执行了一个切换管道
如何做到这些呢?这个过程包含一些我们必须要做的工作:
可以重用组件Home,因为重新渲染后,组件Home依然保持不变。
需要停用并移除组件News。
启用并激活组件Message。
在执行步骤2和3之前,需要确保切换效果有效&&也就是说,为保证切换中涉及的所有组件都能按照期望的那样被停用/激活。
切换的各个阶段
我们可以把路由的切换分为三个阶段:可重用阶段,验证阶段和激活阶段。
我们以home/news切换到home/message为例来描述各个阶段。(以下文字描述参考:http://router.vuejs.org/zh-cn/pipeline/index.html)
1. 可重用阶段
检查当前的视图结构中是否存在可以重用的组件。这是通过对比两个新的组件树,找出共用的组件,然后检查它们的可重用性(通过 canReuse 选项)。默认情况下, 所有组件都是可重用的,除非是定制过。
2. 验证阶段
检查当前的组件是否能够停用以及新组件是否可以被激活。这是通过调用路由配置阶段的canDeactivate 和 canActivate 钩子函数来判断的。
3.激活阶段
一旦所有的验证钩子函数都被调用而且没有终止切换,切换就可以认定是合法的。路由器则开始禁用当前组件并启用新组件。
此阶段对应钩子函数的调用顺序和验证阶段相同,其目的是在组件切换真正执行之前提供一个进行清理和准备的机会。界面的更新会等到所有受影响组件的 deactivate 和 activate 钩子函数执行之后才进行。
data 这个钩子函数会在 activate 之后被调用,或者当前组件组件可以重用时也会被调用。
本文主要介绍了以下内容:
介绍编写单页面应用的基本步骤
介绍嵌套路由
介绍具名路径
介绍路由对象
介绍钩子函数和执行顺序
介绍组件切换控制流水线
posted @ 请注意,本站信息均收集自互联网,相关信息仅供参考,医疗等重要信息请以正规途径为最终意见,本站不承担任何责任!
您可能还关注

我要回帖

更多关于 vue router文档 的文章

 

随机推荐