路由
在开始之前先讲一下什么是路由,一个东西只要分发了请求就是路由,路由通常根据路由表——一个存储到各个目的地的最佳路径的表——来引导分组转送。
一个请求可以到很多地方,我们需要实现一个东西来判断请求到底是想去哪,这个东西就是router(路由),通常router根url判断
在前端领域,一个客户可能要访问很多个页面,我们需要一个东西来判断客户究竟想访问那个页面,router根据什么来判断的呢,用url。router根据用户需求(url)分别展示页面就是路由(这里的页面和传统意义的页面不一样这里的页面是不跳转的页面只渲染一部分的页面--router-view)
客户眼前有三个页面,客户都可以访问,他点击第一个页面代表他想去第一个页面,他点击的同时发送给router一个url,router接受到url知道了客户想去哪,然后返回页面
三种实现方式
hash,history,memory
hash路由,router根据url中的#xxx,来判断用户想去哪,这样对SEO不友好,SEO每次只能检索默认路由,因为#锚点不会在请求中显示,SEO不停地curl时只能curl到不带锚点的url,此时只会显示默认锚点
history后端将所有前端路由都渲染同一页面不能是404,ie8不支持,a标签如果只有“#xxx” “/xxx”,那么浏览器会自动在#和/之前补充之前的域名+端口号,加/时会跳转
比如这个 URL:www.abc.com/#/hello,has… 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)添加新记录后,浏览器地址栏立刻显示example.com/2.html
,但并不会跳转到2.html
,甚至也不会检查2.html
是否存在,它只是成为浏览历史中的最新记录。
hash和history模式共同特点就是都需要url来判断(a标签),#和/都不会跳转页面
为什么需要后端将所有前端路由都渲染同一页面?
因为pushState()并不会跳转页面,只是路径改变了,前端需要根据路径变化来渲染不同东西,但是不跳转页面
memory(不是url都是memory)--前端常使用localstorage或者本地数据库,常在非浏览器因为app没有路径
Vue.js + Vue Router 创建单页应用
模板语法
使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 Vue Router 添加进来,我们需要做的是,将组件 (components) 映射到路由 (routes),然后告诉 Vue Router 在哪里渲染它们。
下面是App.vue文件
<div id="app">
<p>
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
1. <router-link> 默认会被渲染成一个 `<a>` 标签,to后面的链接和router.js文件中设置的一样,
2. 点击两个a标签,会自动根据router文件,渲染相应组件
3. router-view就是路由出口,将a标签匹配到的组件渲染到这里
4. <router-link>的作用就是跳转路由,我们可以如上图直接把link写在App.vue里面,也可以变成组件
<div id="app">
<router-view></router-view>
</div>
5. router-view一开始打开页面的路由是/,我们可以设置路由为 / 时渲染某个组件,在默认路由组件中引入含有link的组件即可,也可以在main.js定义全局组件,这样默认路由直接用即可,不必引入
router语法
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' } //声明组件或者引入组件
const routes = [
{ path: '/foo', component: Foo }, //路由表
{ path: '/bar', component: Bar } // 每个路由应该映射一个组件。
]
const router = new VueRouter({
routes: routes //创建 router 实例,然后传 `routes` 配置 //
}) //把对url的操作封装起来
// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
router
}).$mount('#app')
// hash模式 - window.location.hash.substr( 1 )
// history模式 -window.location.pathname
两个模式都不会跳转(非传统页面)
a.addEventListener("click", e => { e.preventDefault(); //监听a标签,组织a标签跳转 const href = a.getAttribute("href"); //但可以拿到href window.history.pushState(null, `page ${href}`, href); //根据href来路由 onStateChange(href);
}
history模式下路径变了,但是没有跳转只是重新渲染,按理来说点击a标签应该改变url跳转的但是没有被阻止了,a标签的作用只剩下了传递href,改变url的任务交给了historyAPI。
有两种方式点击a标签和直接在地址栏输入,上面分析了点击a标签,那么直接在地址栏输入呢?
这就需要后端将所有前端路由都渲染同一页面不跳转,具体渲染由前端的代码实现
======================================================
通过注入路由器,我们可以在任何组件内通过 this.$router
访问路由器,也可以通过 this.$route
访问当前路由:
methods: {
goBack() {
window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/')
}
}
留意一下 this.$router
和 router
使用起来完全一样。我们使用 this.$router
的原因是我们并不想在每个独立需要封装路由的组件中都导入路由。
<router-link>
对应的路由匹配成功,将自动设置 class 属性值 .router-link-active
。
路由顺序判断
vue router是顺序判断的,把404路由放在末尾即可
总结
路由
前端领域,一个客户可能访问多个页面,我需要一个东西来判断客户想访问哪个页面,这个东西就是路由。
hash路由
hash路由和history路由都是根据url内容选择渲染的,借助于点击a标签url会改变但页面不会刷新,hash路由在url后面加上#,由于url加#并不会跳转,所以我们根据url的#后面的内容选择性渲染在同一页面
优点:所有浏览器都支持#
缺点:seo不友好,请求中不会出现#,所有在seo眼中永远都是默认的渲染
history路由
history路由,借助于a标签上的href,history路由在url后面加上/,我们根据url的/后面的内容选择性渲染在同一页面,问题在于加 / 时会跳转啊!因此我们需要组织a标签的默认行为,用historyAPI来改变url。
局限:点击a标签我们可以用api来修改url,但是直接地址栏输入就需要后端将所有前端路由都渲染同一页面不跳转,这样我们输入/xxx都不会跳转而是会选择渲染,如果页面不一样那么跳转就会是全新的页面
区别
hash是点击a标签时改变url,history是用historyAPI来改变url的
共同点
两个路由是不会跳转的(发起请求的)hash是本身就不请求,history是阻止了请求以及服务端路由都是一个页面,是局部选择渲染