vue路由 大神总结 https://github.com/wike933/vuebook
前言: 学习VUE几个月,看了很多例子和资料,vue虽然中文文档比较多,但是都是一些零散的教程,我这里打算写一本完整的VUE2.0的开发教程(因为时间有限,每天更新一小块,希望大家支持) 本人QQ :200569525 你想学什么,或者有什么疑问 可以联系我
正文:
第一步安装vue
我们一般使用vue-cli
全局安装 vue-cli
$ npm install --global vue-cli
创建一个基于 webpack 模板的新项目
$ vue init webpack my-project
安装依赖
$ cd my-project
$ npm install
$ npm run dev
这个虽然可以运行,但是根据现有开发环境有些地方需要配置(例如静态资源目录,后台数据代理)
进入到目录 config 打开index.js文件
找到 assetsSubDirectory: './',
这里配置成当前目录,意思时静态文件夹按照./为资源根目录
找到 index: path.resolve(__dirname, '../../dist/index.html'),
设置打包后的HTML路径
找到 assetsRoot: path.resolve(__dirname, '../../dist'),
设置打包后资源目录
找到 port:8080,
这里是设置开发环境的服务器断口(可以设置成3000)
找到 proxyTable
这个是设置代理的,我们经常后台和前端同时开发,后台自己起一个服务,如果不配置代理需要每次VUE修改就重启所以我们开发环境配置一个代理,这样开发环境就可以不需要编译,就能与后台数据传输。
(重点)
这里说明下,有的同学不理解 我们一般vue-cli开发是启动npm run dev
这个时候默认开启是 http://localhost:8080 或者http://localhost:3000, 这个时候如果假设我要和后台交互发送AJAX这个时候就跨域了(因为后台端口不是这2个,一个端口不能启动2个应用程序),如果不配置代理就无法请求,如果要请求只能 npm run bulid
编译打包,放到服务器(后台)的静态资源目录,这样修改就需要每次都编译,如果配置了代理 使用开发环境这样修改就及时更新( http://localhost:8080 这样搭建的服务器你vue修改 他会及时反应),开发效率就非常高
proxyTable: {
'/api' :{
target: 'http://127.0.0.1:3000', // 目标域名
pathRewrite:{"^/api":""},
secure:false
}
},
以上配置是 当你AJAX请求 假设请求/api/xxx的连接时,系统会自动代理到 ** 127.0.0.1:3000/xxx** 下(如果请求不是以/api开头那不进行重定向,访问的还是localhost+端口),这样代理就转发, 我们一般在main.js定义一个全局变量 xhr="/api"
然后ajax里面写 $.get(xhr+"/test/")
,在正式环境将xhr赋值为空字符串,这样开发环境使用代理, 非开发环境使用正式路径。
重点
这个地方很多人忘记改,很坑。会导致静态资源渲染时候出错。提醒大家一定要改 进入 build 打开 dev-server.js 找到
app.use(staticPath, express.static('./static'))
替换成
app.use(staticPath, express.static('./'))
这样上面配置的静态资源就是根目录开始,不然需要多个static目录
###下面讲解vue开发以及一些技巧
首当其中的是 main.js
import Vue from 'vue'
import App from './App' //引入根模块
import router from './router' //引入路由
import store from './store/' //引入全局数据管理
window.xhr="/api" 定义全局属性,用于AJAX前缀
如果需要造假数据 index.html 需要引入 <script src="http://mockjs.com/dist/mock.js"></script>
var Random = Mock.Random
Random.ctitle()
var data = Mock.mock({
'list|8': [{
'id|+1': 1,
"title":'@ctitle'
}],
});
Mock.mock("/notice.json", function(options) {
console.log(options)
return data
})
这个时候你就可以 $.get('/notice.json/')
获得假数据,关于mock的用法详情请参考官网 http://mockjs.com/
注意
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
以上代码必须在mock的逻辑之后,不然会出现请求404
//这里写 mock代码
/*
所有mock代码全部写完,这个时候绑定vue插件
*/
new Vue({
el: '#app', //绑定到指定Id的元素下(可以不管)
router, //这里是注册路由(这个写法等于 router:router)
store, //这里是注册全局数据管理的注入 这个写法等于 {store:store}
template: '<App/>', //这个定义魔板 默认就行
components: { App } //这里是引入根组件 (默认是app.vue)这个写法等同于 components: { App:App}
###根组件 app.vue
<template>
<div id="app">
<router-view></router-view> //这个定义路由模板
</div>
</template>
<script>
export default {
name: 'app' //这里定义组件名
}
</script>
<style>
</style>
注意
这里的template必须有一个根元素
<template>
<div id="app">
<router-view></router-view>
</div>
<div id="app2">
<router-view></router-view>
</div>
</template>
这种情况是不允许的
现在我们是单一<router-view>
假设我一个模板中需要多个组件路由我们可以这样
<div>
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
</div>
路由文件./router/index.js
(详细的等会介绍)这样写
import Vue from 'vue'
import Router from 'vue-router'//引入路由
import Hello from '@/components/Hello' //引入组件
import Hello1 from '@/components/Hello1' //引入组件
import Hello2 from '@/components/Hello2' //引入组件
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', //路由路径
name: 'Hello', //路由别名
components: { //路由包含的组件
default: Hello, //这个是默认的 对应 <router-view class="view one"></router-view>
a: Hello1, //这个对应 <router-view class="view two" name="a"></router-view>
b: Hello2 //这个对应 <router-view class="view two" name="b"></router-view>
}
}
]
})
路由文件
import Vue from 'vue' //引入vue
import Router from 'vue-router' //引入路由
import Hello from '@/components/Hello' //引入组件
Vue.use(Router)
//基本路由
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component:Hello
}
]
})
以上是常规路由 path代表匹配的路径,name代表这个路由的名称,component代表路由 router-view
替代的组件。以上路由匹配路径localhost:8080/#/
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: Hello
}
]
})
以上路由是动态参数路由,:id转化成路由的附带参数,以上匹配路径 localhost:8080/user/111
。在VUE实例中调用this.$route.params.id
; 就会得到111
const router = new VueRouter({
routes: [
{
path: '/user/:name/id/:id',
component: Hello
}
]
})
以上路由匹配路径 localhost:8080/user/wike/id/222
在VUE实例中调用 this.$route.params
; 就会得到{name:"wike",id:222}
以上的方法个人觉得不如使用 this.$route.query
好 ,不过在特定情况下还是挺好用的。
嵌套路由
const router = new VueRouter({
routes: [
{ path: '/user', component: User,
children: [
{
// 当 /user/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
上面声明了一个父子路由,User组件的模板中有 router-view 例如:
<template>
<div id="app">
<p>大家好我是组件user</p>
//子路由的占位符
<router-view></router-view> (这里将根据路由路径不同渲染成UserProfile或者UserPosts组件)
</div>
</template>
路由判断是否有进入权限
在main.js 里面加上如下代码
router.beforeEach(function (to,from,next) {
console.log(to) //跳转的目标路由
console.log(from) //跳转之前的路由
if(to.meta.login){ //判断是否有to.meta.login这个属性,如果有则需要验证路由
if($.cookie('user')){ //判断是否有cookie有则进入目标路由
next()
}else{
next({path:'/login'}) //没有则跳转登录页
}
}else{
next() //不需要验证权限的情况直接进入目标路由
}
})
路由index.js声明如下
export default new Router({
linkActiveClass:'hover', //设置当前路由匹配的连接高亮的样式名称
routes: [
{
path: '/',
name: 'Hello',
component:Hello
meta:{login:true}
},
{
path: '/login',
name: 'login',
component:login
}
]
})
路由跳转
设置跳转路由
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
这个等价于
<router-link :to="...">
路由替换
设置当前路由替换这个不会新增加一条历史记录而是替换当前的路由
router.replace(...)
<router-link :to="..." replace>
路由返回
跳到指定的路由栈中,与history.go(n)类似
router.go(n)
关于路由高亮
如果你设置了路由高亮默认情况 http://localhost:8080/#/
这个会匹配所有带/
的高亮情况,也就是他匹配 /
,/hello
等等,这样就会造成高亮混乱,所以我们设置/#/
成为/#/index
只有是/index情况下才会高亮,将/
默认跳转到/index
代码如下
export default new Router({
linkActiveClass:'hover',
routes: [
{
path: '/index',
name: 'Hello',
component:Hello
},
{
path: '/',
redirect:'/index'
},
]
})