目录
3. 通过vue的路由可实现多视图的单页Web应用(基于html的SPA)
3.6 前面使用RouterLink和RouterView组件导航和显示
什么是SPA?
单页应用的全称是 single-page application,简称 SPA,它是一种网站应用的模型,它可以动态重写当前的页面来与用户交互,而不需要重新加载整个页面。单页应用的流畅性让 Web 应用更像桌面端或 Native 应用了。相对于传统的 Web 应用,单页应用做到了前后端分离,后端只负责处理数据提供接口,页面逻辑和页面渲染都交给了前端。前端发展到现在,单页应用的使用已经很广泛,目前时兴的 React、Vue、Angular 等前端框架均采用了 SPA 原则。单页应用意味着前端掌握了主动权,也让前端代码更复杂和庞大,模块化、组件化以及架构设计都变得越来越重要。
说白了 就是整个使用流程里浏览器由始至终没有刷新,整个webapp就一个html文件,里面的各个功能页面是javascript通过hash,或者history api来进行路由,并通过ajax拉取数据来实现响应功能。因为整个webapp就一个html,所以叫单页面!
当然任何东西都有两面性,以下是总结目前 SPA 的一些优缺点:
单页面应用的优缺点:
它的优点有三点:
(1)良好的交互式体验,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
(2)基于上面所说,SPA 对服务器的压力小;
(3)前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理。
它的缺点有四点:
(1)初次加载耗时多,为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载(可以使用路由懒加载解决)
(2)由于单页应用在一个页面中显示,所以不可以使用浏览器自带的前进后退功能,想要实现页面切换需要自己进行管理
(3)SEO 难度较大,由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。
(4)有兼容性问题,部分平台不支持pushstate
为什么页面切换快?
页面每次切换跳转时,并不需要做html文件的请求,这样就节约了很多http发送时延,我们在切换页面的时候速度很快。
缺点:首屏时间慢,SEO差
单页应用的首屏时间慢,首屏时需要请求一次html,同时还要发送一次js请求,两次请求回来了,首屏才会展示出来。相对于多页应用,首屏时间慢。
SEO效果差,因为搜索引擎只认识html里的内容,不认识js的内容,而单页应用的内容都是靠js渲染生成出来的,搜索引擎不识别这部分内容,也就不会给一个好的排名,会导致单页应用做出来的网页在百度和谷歌上的排名差。
有这些缺点,为什么还要使用Vue呢?
Vue还提供了一些其它的技术来解决这些缺点,比如说服务器端渲染技术,通过这些技术可以完美解决这些缺点,解决完这些问题,实际上单页面应用对于前端来说是非常完美的页面开发解决方案。
mm | 多页应用模式MPA | 单页应用模式SPA |
---|---|---|
应用构成 | 由多个完整页面构成 | 一个外壳页面和多个页面片段构成 |
跳转方式 | 页面之间的跳转是从一个页面跳转到另一个页面 | 页面片段之间的跳转是把一个页面片段删除或隐藏,加载另一个页面片段并显示出来。这是片段之间的模拟跳转,并没有开壳页面 |
跳转后公共资源是否重新加载 | 是 | 否 |
URL模式 | http://xxx/page1.html 和 http://xxx/page2.html | http://xxx/shell.html#page1 和 http://xxx/shell.html#page2 |
用户体验 | 页面间切换加载慢,不流畅,用户体验差,特别是在移动设备上 | 页面片段间的切换快,用户体验好,包括在移动设备上 |
能否实现转场动画 | 无法实现 | 容易实现(手机app动效) |
页面间传递数据 | 依赖URL、cookie或者localstorage,实现麻烦 | 因为在一个页面内,页面间传递数据很容易实现(这里是我补充,父子之间传值,或vuex或storage之类) |
搜索引擎优化(SEO) | 可以直接做 | 需要单独方案做,有点麻烦 |
特别适用的范围 | 需要对搜索引擎友好的网站 | 对体验要求高的应用,特别是移动应用 |
搜索引擎优化(SEO) | 可以直接做 | 需要单独方案做,有点麻烦 |
开发难度 | 低一些,框架选择容易 | 高一些,需要专门的框架来降低这种模式的开发难度 |
2. SPA实现思路和技术点
1 ajax
2 锚点的使用(window.location.hash #)
3 hashchange 事件 window.addEventListener("hashchange",function () {})
4 监听锚点值变化的事件,根据不同的锚点值,请求相应的数据
5 原本用作页面内部进行跳转,定位并展示相应的内容
3. 通过vue的路由可实现多视图的单页Web应用(基于html的SPA)
3.1 引入依赖库
<!-- 引入vue.js -->
<script src="js/vue.js" type="text/jscript"></script>
<!-- 引入vue-router.js(路由) -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.5.0/vue-router.js"></script>
3.2 创建自定义组件,例如:Home和Abort组件
//2.创建自定义组件
const Home=Vue.extend({template:'<div><h1>首页</h1><div>首页的内容地方</div></div>'});
const About=Vue.extend({template:'<div><h1>关于</h1><div>关于的内容地方</div></div>'});
注1:extend是构造一个组件的语法器. 你给它参数,他给你一个组件,然后这个组件
你可以作用到Vue.component这个全局注册方法里,也可以在任意vue模板里使用car组件
注2:也可以用以前的方式创建和获得组件,效果也是一样的
Vue.component("button-counter", {...});//创建组件
var ButtonCounter = Vue.component('button-counter');//获得组件
3.2.定义路由(即路线),
//3.定义路由
var routes=[
{name:'Home',path:'/Home',component:Home},
/* {name:'About',path:'/',component:About} */
{name:'About',path:'/About',component:About}
];
注1:根路径“/”
3.4 创建路由器实例,然后传 `routes` 配置
const router=new VueRouter({routes:routes});
注1:route和router的区别
route:路线
router:路由器
路由器中包含了多个路线
3.5.创建和挂载根实例。
var vm=new Vue({
//el:'#app',
router:router,
data:function(){
return{
ts:new Date().getTime()
}
},
methods:{
goto:function(){
},
back:function(){
},
change:function(){
this.$router.push('/Home');
}
}
}).$mount('#app');
3.6 前面使用RouterLink和RouterView组件导航和显示
<!-- 使用RouterLink组件导航. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<!-- 通过传入 `to` 属性指定链接. -->
<router-link to="/home">go to Home</router-link>
<!-- 使用RouterView组件显示. -->
<router-view></router-view>
4. router-link相关属性
4.1 to
表示目标路由的链接
<router-link to="/home">Home</router-link><!-- 字符串 -->
<router-link v-bind:to="'home'">Home</router-link><!-- 使用 v-bind 的 JS 表达式 -->
4.2 replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。
<router-link :to="{ path: '/home'}" replace></router-link>
vue中导航中的后退-前进-编程式导航
this.$router.go(-1) :代表着后退
this.$router.go(1):代表着前进
this.$router.push({ 切换到name为home的路由
name:'home'
});
4.3 append
设置 append 属性后,则在当前 (相对) 路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
<base herf="${pageContext.request.contextPath}/"/>
base标签作用于head标签之间在link和script标签中的href和src属性之前加入
<base href="/vue04/">
<script src="js/vue.js">
<!-- base中href+script标签中的src /vue04/js/vue.js-->
<router-link :to="{ path: 'relative/path'}" append></router-link>
4.4 有时候想要 <router-link> 渲染成某种标签,
例如 <li>。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航
<router-link to="/foo" tag="li">foo</router-link>
<!-- 渲染结果 -->
<li>foo</li>
4.5 active-class
设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代
4.6 exact-active-class
配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。
4.7 event
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。
<router-link v-bind:to = "{ path: '/route1'}"
5.综合代码演示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<!-- 引入vue.js -->
<script src="js/vue.js" type="text/jscript"></script>
<!-- 引入vue-router.js(路由) -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.5.0/vue-router.js"></script>
<body>
<div id="app">
<h1>{{ts}}</h1>
<div>
<button @click="goto()">前进</button>
<button @click="back()">后退</button>
<button @click="change()">切换</button>
</div>
<div>
<router-link to="/Home" tag="li">首页</router-link>
<router-link to="/About" replace>关于</router-link>
</div>
<div>
<router-view/>
</div>
</div>
</body>
<script>
//1.引入vue.js和vue-router.js
//2.创建自定义组件
const Home=Vue.extend({template:'<div><h1>首页</h1><div>首页的内容地方</div></div>'});
const About=Vue.extend({template:'<div><h1>关于</h1><div>关于的内容地方</div></div>'});
//3.定义路由
var routes=[
{name:'Home',path:'/Home',component:Home},
/* {name:'About',path:'/',component:About} */
{name:'About',path:'/About',component:About}
];
//4.定义路由器(包含多路由)
const router=new VueRouter({routes:routes});
//5.创建和挂载根实例。
var vm=new Vue({
//el:'#app',
router:router,
data:function(){
return{
ts:new Date().getTime()
}
},
methods:{
goto:function(){
this.$router.go(1);
},
back:function(){
this.$router.go(-1);
},
change:function(){
/* this.$router.push({
name:'About'
}); */
this.$router.push('/Home');
}
}
}).$mount('#app');
</script>
</html>
6.运行效果图