一、前端渲染与后端渲染
在web开发的早期都是使用后端渲染,如jsp(java server page),php等等
前端渲染流程:先由浏览器发送一个 url(api接口地址) 到服务端(API接口服务器),服务端(API接口服务器) 再解析 url(api接口地址),然后 服务端(API接口服务器) 再返回大量数据给浏览器,浏览器再通过js代码(创建DOM) 把数据渲染到页面上
后端渲染流程:先由浏览器发送一个url(静态地址) 到服务端(静态资源服务器),服务端(静态资源服务器) 再解析url(静态地址),服务端(静态资源服务器) 然后在服务器里开始渲染一个页面,页面里面有html+css+java代码(java代码是用于从数据库读取数据并动态添加到页面内),最后把这个页面直接传到浏览器,而传来的页面里面只有html+css+一些数据(静态页面),这个网页就是最终的页面了
前端渲染优点:页面具有逻辑,利于前后端分离等等
后端渲染优点:有利于SEO的优化,不占用客户端运算资源
如果还不理解可以点击这里查看前后端渲染的区别与解释
来源:https://segmentfault.com/q/1010000009359167
作者:rife
二、前端路由与后端路由
什么是路由?
路由是决定数据包从来源到目的地的路径,把输入端的数据转送到合适的目的地,而路由器里面有一个映射表,它决定了数据包的ip地址的映射,而 前端路由与后端路由也是一种映射关系
前端路由:因为single-page application (SPA)单页面复应用,所以浏览器向后端请求了html+css+js,但是需要管理不同url与不同网页映射关系,所以就有了前端路由,所以 前端路由就是在浏览器管理url与不同页面的关系 ,优点是在 改变url时,页面不进行整体刷新
后端路由:由 后端(静态资源服务器)处理url与不同页面之间的映射关系叫后端路由
三、如何改变url页面却不发生跳转
url的hash
location.hash = 'foo'
HTML5的history
pushState()
/*有历史记录,可以返回以前页面,而且它的数据结构为栈,此时为入栈*/
history.pushState({}, '', 'foo')
back()
/*返回页面,只能back,而且它的数据结构为栈,此时为出栈*/
history.back()
replaceState()
/*无历史记录,不可返回以前页面*/
history.replaceState({}, '', 'foo')
go()
/*返回或者前进页面,是back与forward的加强,而且它的数据结构为栈*/
history.go(1)
forward()
/*前进页面,只能forward,而且它的数据结构为栈,此时为入栈*/
history.forward()
四、vue-router基础使用
目前的三大框架都有自己的路由实现:Angular的ngRouter,React的ReactRouter,Vue的vue-router
vue-router是Vue.js官网的插件,是和vue.js深度集成的,适合构建单页面应用。vue-router用于 设定访问路径,把路径与组件映射起来,所以在vue-router的单页面应用程序里面,页面路径的改变就是组件的切换
vue-router的安装与配置:
vue-router的使用:
import VueRouter from 'vue-router' /*引入vue-router*/
Vue.use(VueRouter) /*安装路由*/
const Home = () => import('../views/Home'); /*引入Home组件*/
const routes = [
{ /*设置路由*/
path: '/',
redirect: '/home'
}
]
const router = new VueRouter({ /*实例化VueRouter对象*/
mode: 'history',
routes
})
new Vue({
router, /*在Vue上面挂载router对象*/
render: h => h(App)
}).$mount('#app')
要注意每一次引入插件,都必须要先安装,而安装需要使用Vue.use(插件),因为只要一使用它,它内部就会取执行VueRouter.install这方法
$router为一个 全局的VueRouter对象,想要导航到不同URL,则使用$router
<router-link>:该标签是一个vue-router内置的组件,它会默认渲染成a标签
也可以通过以下代码修改url:
this.$router.push('/home') /*相当于history.pushState({}, '', 'home'),有历史记录*/
this.$router.replace('/home') /*相当于history.replaceState({}, '', 'home'),无历史记录*/
<router-view>:根据不同的路径渲染不同的组件
路由默认修改的url是通过修改url的hash来实现的,不过可以通过mode来修改为history
建议使用mode,因为使用hash路径会很怪异(有个井号),如:http://192.168.0.2:8080/#/about
五、动态路由
因为url的地址并不是一成不变的,比如说不同的用户登陆自己的用户中心,url后面的信息就会不相同
例如:https://…/user/lisi
{
path: '/user/:username', /*动态路由: /冒号 + 属性名*/
name: 'User',
component: () => import('../views/User') /*懒加载*/
}
$route为当前router跳转处于活跃的对象,且里面可以获取name、path、query、params等
/*this.$route.params.username来获得路由传过来的数据*/
<h2>{{ this.$route.params.username }}</h2>
六、路由的懒加载
当我们在打包构建应用的时候,js包会变得很大,影响页面加载,所以我们需要把不同的路由组件分割成==不同的代码块=,然后当路由被访问的时候才可以快速加载出来
/*路由懒加载使用箭头函数即可,建议使用*/
component: () => import('../views/User')
七、路由嵌套
/*配置子路由*/
……
{
path: '/home', /*这里需要加 / */
name: 'Home',
component: Home,
children: [
{
path: '/',
redirect: 'news'
},
{
path: 'news', /*子路由是不需要在路径前面加 / 的*/
component: HomeNews
},
{
path: 'messages',
component: HomeMessages
}
]
},
……
/*子路由使用*/
<router-link to="/home/news">News</router-link> | /*注意这里路径前面必须要有 / */
<router-link to="/home/messages">Messages</router-link>
<router-view></router-view>
八、vue-router的传递参数
他是通过url来传数据的
URI = scheme:[//authority]path[?query][#fragment]
params和query
/*query写法*/
<router-link :to="{path: '/profile', query: {name: '毛毛', age: 20}}" >Profile</router-link>
/*使用url传递的参数*/
<h2>{{ $route.query.name }}</h2>
<h2>{{ $route.query.age }}</h2>
九、$router与$route的区别
$router: 任何组件 拿到的 $router对象 就是new VueRouter实例对象,且这个路由是 全局路由
为什么会这样呢?
首先所有组件都继承于Vue的原型,而在使用路由的时候,Vue会使用 Object.defineProperty()方法 把实例化的VueRouter对象添加到Vue.prototype里面,所以所有的组件里面都有$router属性,且它指向 VueRouter实例对象
$route:$route是指当前处于活跃的路由对象
为什么呢?
这个与上面的相同,也是在使用路由的时候,Vue会使用 Object.defineProperty() 方法把 $route对象 添加到Vue.prototype里面,且 这个$route对象是动态获得的 ,所以所有的组件里面都有$route属性,且它指向 动态获得的$route对象
十、vue-router导航守卫
导航守卫最主要的作用就是监听导航的跳转
全局守卫:
/*Vue源码里面的导航守卫函数*/
beforeEach(guard: NavigationGuard): Function
afterEach(hook: (to: Route, from: Route) => any): Function
beforeEach(guard: NavigationGuard)的使用
/*main.js文件里面使用router(路由)的beforeEach()方法,涵义为:在路由跳转之前执行里面的箭头函数*/
/*这里的to是即将进入目标的路由对象*/
/*这里的from是即将离开的路由对象*/
/*这里必须要调用next()方法,才可以进入下一个钩子,也就是程序才可以正常的运行*/
router.beforeEach((to, from, next) => {
document.title = to.matched[0].meta.title;
console.log(to);
next();
})
/*配置路由meta属性*/
……
{
path: '/about',
name: 'About',
component: About,
meta: {
title: 'about'
}
},
{
path: '/user/:username',
name: 'User',
component: User,
meta: {
title: 'user'
}
}
……
afterEach(hook: (to: Route, from: Route) => any)的使用
/*main.js文件里面使用router(路由)的afterEach()方法,涵义为:在路由跳转之后执行里面的箭头函数*/
/*这里的to是即将进入目标的路由对象*/
/*这里的from是即将离开的路由对象*/
/*这里没有next()*/
router.afterEach((to, from) => {
console.log('lll'); /*跳转之后打印的内容*/
})
全局守卫具体可以参看官网里面的全局守卫
组件守卫:
/*组件守卫*/
beforeRouteEnter (to, from, next)
beforeRouteUpdate (to, from, next)
beforeRouteLeave (to, from, next)
使用和上面相同,组件守卫具体可以参看官网里面的组件守卫
十一、vue-router的keep-alive
keep-alive
keep-alive是Vue内置的一个组件,可以使被包含的组件保持状态,避免重新渲染
router-view是vue-router内置的一个组件,如果它被包在keep-alive,则所有路径匹配到的视图组件都会被缓存,组件就不会被destroyed
/*使用keep-alive包裹router-view*/
/*组件内定义,且created()与destroyed()是生命周期函数*/
created() {
console.log('home created'); /*create只打印一次,因为没有销毁所以不会重建*/
},
destroyed() {
console.log('home destroyed'); /*在没有被销毁前不会打印*/
},
activated() {
console.log('home activated'); /*只有有keep-alive标签包裹的router-view标签对应的路由才有activated()方法,在活跃时触发*/
},
deactivated() {
console.log('home deactivated'); /*只有有keep-alive标签包裹的router-view标签对应的路由才有deactivated()方法,在不活跃时触发*/
}
keep-alive标签的属性
/*exclude属性*/
<keep-alive exclude="User,Profile"> /*属性内包含着的内容为组件的name属性(必须有name才可以exclude),且逗号后面不能有空格,
因为vue是把exclude内的值当成字符串来解析,有空格会干扰解析,下同*/
/*但是如果有空格,那么该组件就不会被exclude或者被include,因为识别不到*/
<router-view/>
</keep-alive>
<keep-alive include="Home"> /*属性内包含着的内容为组件的name属性,且逗号后面不能有空格*/
<router-view/>
</keep-alive>
exclude、include、正则表达式 的逗号后面都不能有空格
十二、图解
题外话:
现实公司中,服务器一般指静态服务器和提供API接口的服务器
meta:元数据,解释数据的数据
本文只用于个人学习与记录