内容简介:router,路由,我理解的其实就是,让不同的路径对应的不同的视图。在vue里,其实视图就相当于组件。也就是让不同的路径对应不同的组件。换言之,router就是规定了路径和组件一一对应。这句可能是理解vue-touter的核心。怎么用render函数替换template呢?
- router其实就是让路径和组件一一对应
- 即便不使用vue-router也可以实现跳转,但总是手动处理历史记录
- vue-router的使用好处:历史记录、参数处理、路由钩子、权限控制、记录滚动条位置
- vue-router指南 和 vue-router的API
-
坑:历史模式懒加载的时候注意名字、子路由一般不用
/
router到底是什么
router,路由,我理解的其实就是,让不同的路径对应的不同的视图。在vue里,其实视图就相当于组件。也就是让不同的路径对应不同的组件。换言之,router就是规定了路径和组件一一对应。这句可能是理解vue-touter的核心。
先说说render,为下个标题铺垫
vue官网对render解释的很清楚 ,这边我简单的说下。 一般我们写vue组件的时候,会写template,但任何template都可以用render函数代替,事实上,vue就是把template转换为render函数的,之所以我们用template,是因为其易读易写。
怎么用render函数替换template呢?
简单的举个例子,你的template是 <h1 :title="blogTitle">{{ blogTitle }}</h1>
,对应的render函数如下
render: function (createElement) { // `createElement`的参数一般有三个,第一个必填就是标签名或者组件名,第二个是这个标签的属性,第三个就是子节点。 return createElement('h1', {attrs:{title:this.blogTitle}}, [this.blogTitle]) } 复制代码
createElement
其实更准确的名字是 createNodeDescription
,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点,包括及其子节点的描述信息。也就是“虚拟节点 (virtual node)”,简写为“VNode”。“虚拟 DOM”是对由 Vue 组件树建立起来的整个 VNode 树的称呼。
即便不用vue-router,也可以实现单页面跳转的
开始总以为,要想不同路径就必须要 vue-router
,其实不必。 vue官方文档有个很好的demo
,这边挪用下逻辑。如果你只是需要简单的路由,也是可以直接这么用的。
// <div id="app"><div> const Home = { template: "<p>home page</p>" }; const About = { template: "<p>about page</p>" }; const NotFound = { template: "<p>Page not found</p>" }; // 路由 路径和组件一一对应 const routes = {'/':Home,'about':About} var app = new Vue({ el: "#app", data: { // 拿到地址栏路径 currentRoute: window.location.pathname }, computed: { // 由routes得到路径对应的组件 ViewComponent() { return routes[this.currentRoute] || NotFound; } }, // 这边用render了 render(h) { return h(this.ViewComponent); } }); // 历史记录的处理 window.addEventListener('popstate', () => { app.currentRoute = window.location.pathname }) 复制代码
用vue-router有什么好处
- 自己写上面一套繁琐哇
- 不同路径很轻易对应不同组件,而且人家处理好了历史记录
- 轻易解决传参数问题
- 有路由钩子,控制什么情况去什么路径,比如不登录的话就去登录页面
- 甚至可以记住滚动条的位置
官网就是很好的学习路径
vue-router官网,以下我简单的总结下。代码示例统一在末尾。
-
vue-router
分两种模式,history
模式和hash
模式(地址栏有#),hash
模式利用#不会跳转,history
模式利用pushState
和popState
。 -
vue-router增加两个组件
router-link
和router-view
,<router-link to="/foo">Go to Foo</router-link>
相当于<a href="/foo">Go to Foo</a>
,事实上也的确会被渲染成a标签。router-view
是占位符的感觉,会将路径匹配的组件显示在这里。 -
任何组件内都可以通过
this.$router
访问所有路由,访问当前路由this.$route
,多个r就是多的意思,这么记着吧,打印可以看看这两个 -
动态路由也就是不同的路径对应同一个视图
。
path: '*'
匹配所有路由,通常放在最后匹配404(感觉像express)。使用通配符的时候,this.$route.params.pathMatch = *所表示的部分
-
嵌套路由其实就是
/user/create /user/list
这种 。注意的坑是,以/
开头的嵌套路径会被当作根路径,所以一般嵌套的路由是不要/
-
js里跳转到不同的路径的话
,
router.push(location, onComplete?, onAbort?)
相当于<router-link to="/foo">
,replace会替换掉当前的历史记录,go(n)表示前进或者后退。如果 history 记录不够用,那就默默地失败呗。 -
如果同个组件里有多个router-view,怎么显示
,
router-view
跟slot相似,不写name的话,默认name是default,对应的router文件里,components变成对象,{name:组件}
-
别名也就是a路径的时候想要显示b路径的视图,换言之a路径也是b路径的别名
,
{ path: '/b', component: B, alias: '/a' }
-
重定向也就是a路径的时候想要跳转到b路径,从而显示b路径的视图
,
{ path: '/a', redirect: '/b' }
- history模式下前进后退是需要服务器作支持的
-
导航守卫就是希望去某个路径的时候能做些什么事,路由钩子的感觉
,注意的是,参数或查询的改变并不会触发进入/离开的导航守卫,可以通过
watch $route
对象来应对这些变化,或在组件内使用beforeRouteUpdate
。一旦用钩子,请一定确保要调用next
方法,否则钩子就不会被resolved
。想要去每一个路径都要判断时用router.beforeEach(to,from,next)
,next('/user')
可以直接中断去另外的路径,next(false)
中断跳转。如果只是想在去某个路径的时候做些事,可以在对应的路径下,写beforeEnter(to,from,next)
。如果想要禁止用户在还未保存修改前突然离开,可以在组件内设置beforeRouteLeave (to, from , next)
,这里注意next的路径最好不是to.path不然会死循环=。=。 -
有些路径是需要登录才能进去的就需要配置meta了
,routes 配置中的每个路由对象为 路由记录,路由记录可以是嵌套的(有children的时候),因此,当一个路由匹配成功后,他可能匹配多个路由记录。
/foo/bar
这个 URL 将会匹配父路由记录以及子路由记录。meta取的方式 遍历$route.matched 来检查路由记录中的 meta 字段 -
去不同路径的时候想要切换的特效
,能用
<transition name="slide">
解决的就用这个吧 - 跳转路径的时候,希望用路径上面的id请求数据,这个可以在跳转前完成也可以在跳转后完成 ,如果请求很快的话,可以在跳转前,请求慢的话可以在跳转后,根据需要来。
-
控制滚动条的位置
,
scrollBehavior (to, from, savedPosition) { // return 期望滚动到哪个的位置 }
怎么根据路径显示不同组件的的
-
vue拿到 地址栏的路径(如
/user/user-list
) -
=> 找routes 那边的配置,从上到下找 (如
path:'/user'
),拿到components,(如找到{default:Foo,a:Bar}
) -
=> 因为/user就是第一级路径,所以直接将app.vue里面的
<router-view/>
替换成Foo组件
,<router-view name="a"/>
替换成Bar组件
-
=> 再继续,找
path:'/user'
下面的children,发现目标path:'user-list'
,拿到components,找到{default:Second,a:Zoo}
-
=> 因为
user-list
是user的children,所以将user.vue里面的<router-view/>
替换成Second组件
,<router-view name="a"/>
替换成Zoo组件
- 找不到的话会报错,当然一般都会配置404
示例代码
<!-- 示例1 --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <!-- 路由出口 --> <!-- 路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div> <script> // 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter) // 1. 定义 (路由) 组件。也就是视图!!!! // 可以从其他文件 import 进来 const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } // 2. 定义路由。也就是什么路径显示什么视图(组件)!!! // 每个路由应该映射一个组件。 其中"component" 可以是 // 通过 Vue.extend() 创建的组件构造器, // 或者,只是一个组件配置对象。 // 我们晚点再讨论嵌套路由。 const routes = [ { path: '/foo', component: Foo }, // 懒加载模式,会在合适的时机加载 bar.js,webpackChunkName就是将此组件的代码命名为bar.js 看控制台的network { path: '/bar', component: () => import(/* webpackChunkName: "bar" */ './views/Bar.vue'), }, // 注意 404 { path: '*', component: () => import(/* webpackChunkName: "404" */ './views/404.vue'), }, ] ] // 3. 创建 router 实例,然后传 `routes` 配置。 // 你还可以传别的配置参数, 不过先这么简单着吧。 const router = new VueRouter({ routes // (缩写) 相当于 routes: routes }) // 4. 创建和挂载根实例。!!!挂载在根实例下,也就是任何组件内都可以通过this.$router知道内容 // 记得要通过 router 配置参数注入路由, // 从而让整个应用都有路由功能 const app = new Vue({ router }).$mount('#app') // 现在,应用已经启动了! </script> 复制代码
// 示例1 js // Home.vue export default { computed: { username () { // 我们很快就会看到 `params` 是什么 return this.$route.params.username } }, methods: { goBack () { window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/') } } } 复制代码
/* 示例2:有嵌套路由的话 */ routes: [ { path: '/user/:id', component: User, children: [ { // 当 /user/:id/profile 匹配成功, // UserProfile 会被渲染在 User 的 <router-view> 中 path: 'profile', component: UserProfile }, { // 当 /user/:id/posts 匹配成功 // UserPosts 会被渲染在 User 的 <router-view> 中 path: 'posts', component: UserPosts } ] } ] /* 示例3:router.push使用 */ // push的两种参数情况,尽量用路径的形式,用name的话有时候子路由可能不太方便 // -> /user/123 router.push({ path: `/user/${userId}` }) // 带查询参数,变成 /register?plan=private router.push({ path: 'register', query: { userId }}) // replace router.replace({ path: 'register', query: { userId }}) router.go(1) router.go(-1) /* 示例4:router-view多个的情况 */ <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> { path: '/', components: { default: Foo, a: Bar, b: Baz } } /* 示例5:重定向和别名 */ const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' } // { path: '/b', component: B, alias: '/a' } ] }) /* 示例6:导航守卫 */ const router = new VueRouter({ ... }) // router上面的钩子 router.beforeEach((to, from, next) => { next() // next(false) // next('/') }) router.afterEach((to, from) => { // ... }) const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, // route上的钩子 beforeEnter: (to, from, next) => { // ... } } ] }) // 组件内的钩子 const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` } } /* 示例7:meta的使用 */ const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, children: [ { path: 'bar', component: Bar, // a meta field meta: { requiresAuth: true } } ] } ] }) router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { // this route requires auth, check if logged in // if not, redirect to login page. if (!auth.loggedIn()) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } } else { next() // 确保一定要调用 next() } }) /* 示例8:跳转路径的特效 */ <transition> <router-view></router-view> </transition> const Foo = { template: ` <transition name="slide"> <div class="foo">...</div> </transition> ` } /* 示例9:根据路径的参数去请求数据 这边显示跳转之后请求数据 */ export default { data () { return { loading: false, post: null, error: null } }, created () { // 组件创建完后获取数据, // 此时 data 已经被 observed 了 this.fetchData() }, watch: { // 如果路由有变化,会再次执行该方法 '$route': 'fetchData' }, methods: { fetchData () { this.error = this.post = null this.loading = true // replace getPost with your data fetching util / API wrapper getPost(this.$route.params.id, (err, post) => { this.loading = false if (err) { this.error = err.toString() } else { this.post = post } }) } } } /* 示例10:控制滚动条的位置 */ scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } } 复制代码
写例子来实践
需求:
- 现在总共有四个页面 home profile user login,profile是个人中心的意思
- 然后 user下面有 create-user user-list
- 然后设置 只有登录之后 才能去 profile user 否则就跳转到 login
- 每个页面都有导航条
1.加四个视图和对应的路由
vue create router-apply router-link router-view
2.user那边增加子页面
- views增加 create-user user-list
- router那边配置路径
- user.vue那边增加router-view
3.user子页面能相互跳转,增加的用户跳转的时候传递到user-list
- create-user 有input框和跳转按钮,跳转的时候,带着值,用query的方式
-
顺便还可以设置
/user
路径的时候跳转到/user/create-user
4.设置只有登录才能去profile和user
beforeEach
核心代码展示
// main.js router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.needLogin)) { // this route requires auth, check if logged in // if not, redirect to login page. if (!isLogin) { next({ path: '/login', // 方便登录之后返回来 query: { redirect: to.fullPath } }) } else { next() } } else { next() // 确保一定要调用 next() } }) // router.js { path: '/user', name: 'user', component: () => import(/* webpackChunkName: "user" */ './views/User.vue'), children: [ { path: 'create-user', alias: '', component: () => import(/* webpackChunkName: "createUser" */ './views/CreateUser.vue') }, { path: 'user-list', component: () => import(/* webpackChunkName: "userList" */ './views/UserList.vue') } ], meta: { needLogin: true } } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 大白话 Laravel 中间件
- 大白话讲梯度下降法(一)
- 大白话讲梯度下降法(二)
- 大白话理解和初步使用vuex
- JAVA-大白话探索JVM-类加载过程(二)
- JAVA-大白话探索JVM-运行时内存(三)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
RESTful Web Services Cookbook
Subbu Allamaraju / Yahoo Press / 2010-3-11 / USD 39.99
While the REST design philosophy has captured the imagination of web and enterprise developers alike, using this approach to develop real web services is no picnic. This cookbook includes more than 10......一起来看看 《RESTful Web Services Cookbook》 这本书的介绍吧!
HTML 编码/解码
HTML 编码/解码
HEX HSV 转换工具
HEX HSV 互换工具