路由
- 前端路由
- 后端路由
前端路由
根据对于的url地址来渲染不同的内容
前端路由的分类
- 页面路由 :通过页面的跳转来完成对应的切换,会刷新页面
- hash路由 :通过对应hash值变化来控制内容的渲染(onhashchange),页面不刷新,只有一个页面
- history路由 :通过对应的地址的变化来控制内容的渲染 (onpopstate) ,页面不刷新,只有一个页面
SPA(单页应用程序)
- 单页应用程序 (single page application),顾名思义只有一个页面,通过控制渲染内容来完成对应的页面内容的切换。
- 好处:对应页面的切换操作不再依赖于刷新,减少了页面的重绘和回流,单独一个页面打出来的包的大小也相对较小。
- 坏处:不利于seo(电商网站不可能使用spa)。
- react和vue都是为了减少对应的重绘和回流提高对应的性能,所以它一般都是采用对应的单页面应用。
- SPA主要采用的路由模式为hash路由、history路由。默认情况下为hash模式。
SSR(服务器渲染)
- 服务器渲染利于seo且速度快,但代码量大维护起来较为困难,对于服务器压力大。
- 一般的大型电商网站都是采用 ssr 配合 spa 来共同作用。(前端采用的是 vue 的技术栈、配合 ssr 的框架nuxt.js;前端采用的是 react 配合 next.js)
vue中hash路由实现SPA
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="
viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.min.js"></script>
<script src="./vue-router.js"></script>
<style>
/* 激活的链接 */
.router-link-exact-active {
color: red
}
</style>
</head>
<body>
<!-- 容器 -->
<div id="app">
<!-- 路由链接 to指定的地址 router-link会解析成a标签-->
<router-link to="/">去首页</router-link>
<router-link to="/user">去用户页</router-link>
<!-- 路由视图 显示的视图 router-view会解析你对应需要渲染的内容-->
<router-view></router-view>
</div>
<script>
//组件 渲染的内容
let home = Vue.component('home', {
template: '<div>首页</div>'
})
//渲染的内容
let user = Vue.component('user', {
template: '<div>用户页</div>'
})
//路由对象
let router = new VueRouter({
// mode:'hash', 模式默认为hash
//路由配置 router 名词(路由对象) route 动词(路由配置) routes 多个(路由配置)
routes: [
//route规则
{
name: 'home ', //名字
path: '/', //路由地址
component: home //组件 渲染什么
}, {
name: 'user ',
path: '/user',
component: user
}
]
});
new Vue({
el: '#app',
//传入路由配置 router
// router:router
router
})
</script>
</body>
</html>
自定义模拟hash路由实现SPA
- 利用 onhashchange 事件监听 hash 值的变化
- 通过对应的 routes 规则里面对应的 compoent 内容来渲染
class Vue {
constructor(options) {
//解构获取里面的el和对应的router
let { el, router } = options
this.el = document.querySelector(el) //元素
this.router = router
//调用解析a的方法 将这个this.el当作this
this.router.analysisLink.call(this.el)
this.router.listener(this.el)
}
//返回一个新的组件
static component(name, { template }) {
return new Component(name, template)
}
}
//组件的构造
function Component(name, template) {
this.name = name,
this.template = template
}
//创建VueRouter的类
class VueRouter {
constructor(options) {
//解构获取对应的mode routes
let { mode, routes } = options
//如果mode没有默认为hash模式 如果mode有就是设置模式
this.mode = mode ? mode : 'hash'
this.routes = routes
}
//解析对应的router-link
analysisLink() {
//获取所有的router-link标签
let links = this.querySelectorAll('router-link')
//拿到它的to属性 变成对应的a to属性就是a的href
//遍历
Array.prototype.forEach.call(links, (v) => {
//获取to属性的值
let toValue = v.getAttribute('to')
//先创建对应的a标签 用a标签替换对应的links
let target = document.createElement('a')
target.href = `#${toValue}`
target.innerHTML = v.innerHTML
//替换
this.replaceChild(target, v)
})
}
//解析router-view
// 监听hash值得变化
listener(el) {
//进入就开始渲染
window.onload = () => {
location.hash = '/'
}
//变化的时候进行渲染
window.onhashchange = () => {
this.handler(el)
}
}
handler(el) {
//得到对应的hash值
let hash = location.hash.substring(1)
//根据hash匹配对应的routes里面的path路径 找到对应的route配置
let route = this.routes.find(({ path }) => {
return path == hash
})
//根据route里面component属性 找到对应渲染内容 template
// route.component.template
// 找到router-view标签进行innerHTML赋值
let views = el.querySelectorAll('router-view')
Array.from(views).forEach(v => {
v.innerHTML = route.component.template
})
//样式激活
this.active(el)
}
//匹配当前的hash地址和对应的a标签的链接地址 添加对应的class
active(el) {
//得到hash值
let hash = location.hash.substring(1)
//得到所有的a标签
let links = el.querySelectorAll('a')
// 进行匹配
//排他
Array.prototype.forEach.call(links, v => {
v.className = ''
})
Array.prototype.find.call(links, (v) => {
return v.href.split('#')[1] == hash
}).className = 'router-link-exact-active'
}
}
自定义模拟history路由实现SPA
- onpopstate 进行监听
- 将 a 的内容全部重写,通过 pushState 来完成路径变化
class Vue {
constructor(options) {
//解构获取里面的el和对应的router
let { el, router } = options
this.el = document.querySelector(el) //元素
this.router = router
//调用解析a的方法 将这个this.el当作this
this.router.analysisLink.call(this.el)
this.router.listener(this.el)
}
//返回一个新的组件
static component(name, { template }) {
return new Component(name, template)
}
}
//组件的构造
function Component(name, template) {
this.name = name,
this.template = template
}
//创建VueRouter的类
class VueRouter {
constructor(options) {
//解构获取对应的mode routes
let { mode, routes } = options
//如果mode没有默认为hash模式 如果mode有就是设置模式
this.mode = mode ? mode : 'hash'
this.routes = routes
}
//解析对应的router-link
analysisLink() {
//获取所有的router-link标签
let links = this.querySelectorAll('router-link')
//拿到它的to属性 变成对应的a to属性就是a的href
//遍历
Array.prototype.forEach.call(links, (v) => {
//获取to属性的值
let toValue = v.getAttribute('to')
//先创建对应的a标签 用a标签替换对应的links
let target = document.createElement('a')
target.href = `${toValue}`
target.innerHTML = v.innerHTML
//替换
this.replaceChild(target, v)
})
}
//处理对应的a标签
handlerA(el) {
//获取所有的a标签
let links = el.querySelectorAll('a')
let that = this
//给a标签添加点击事件
Array.prototype.forEach.call(links, (link) => {
link.onclick = function(e) {
e = e || window.event
//禁止刷新
e.preventDefault();
//点击对应的值 通过对应的pushState 来修改对应的页面
history.pushState('', '', this.href)
//渲染
that.handler(el)
}
})
}
//解析router-view
// 监听对应的state的变化
listener(el) {
//监听a的点击事件
this.handlerA(el)
//变化的时候进行渲染
window.onpopstate = () => {
this.handler(el)
}
}
handler(el) {
//得到对应的地址
let localPath = location.pathname
//根据hash匹配对应的routes里面的path路径 找到对应的route配置
let route = this.routes.find(({ path }) => {
return path == localPath
})
//根据route里面component属性 找到对应渲染内容 template
// route.component.template
// 找到router-view标签进行innerHTML赋值
let views = el.querySelectorAll('router-view')
Array.from(views).forEach(v => {
v.innerHTML = route.component.template
})
//样式激活
this.active(el)
}
//匹配当前的地址和对应的a标签的链接地址 添加对应的class
active(el) {
//得到地址
let localPath = location.pathname
//得到所有的a标签
let links = el.querySelectorAll('a')
// 进行匹配
//排他
Array.prototype.forEach.call(links, v => {
v.className = ''
})
Array.prototype.find.call(links, (v) => {
let url = new URL(v.href)
return url.pathname == localPath
}).className = 'router-link-exact-active'
}
}
Sass
Sass它底层采用的是python环境 Ruby语言书写,支持基本的css语法,最终还是会编译成对应的css,它在node环境中不需要你手动编译它会自动编译(sass-load的包)。
Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能
Sass和Less的区别和共性 *
- Sass和Less都是动态样式语言,用来预编译css,都会创建一个 .css文件
- Less基于JavaScript,在客户端处理。
- Sass基于Ruby,在服务器端处理。
- Sass有函数、进程控制、数组的概念
- Less变量使用@定义;Sass使用$定义,它定义的变量有全局和局部之分,并且有优先级。
- Less是通过客户端处理的,Sass是通过服务端处理,相比较之下Less解析会比Sass慢一点
- Sass中有以下进程控制
-条件:@if @else;
-循环遍历:@for @each @while
-继承:@extend
-引用:@importLess和Sass在语法上有些共性,比如下面这些:
1、混入(Mixins)——class中的class;
2、参数混入——可以传递参数的class,就像函数一样;
3、嵌套规则——Class中嵌套class,从而减少重复的代码;
4、运算——CSS中用上数学;
5、颜色功能——可以编辑颜色;
6、名字空间(namespace)——分组样式,从而可以被调用;
7、作用域——局部修改样式;
8、JavaScript 赋值——在CSS中使用JavaScript表达式赋值。
sass的编译环境
- 借助node来进行编译
按照对应的sass及sass-load
npm i sass,sass-load
- 借助第三方插件来进行编译
vscode插件:live Sass Compiler、easy sass
sass的书写
-
sass后缀:以缩进作为区分,没有分号和大括号(:、{}),跟stylus一样
sass编译前:
div
color:#fff
a
color:#ccc编译后:
div {
color: #fff;
}
div a {
color: #ccc;
}
-
scss后缀:和css语法一样
scss编译前:
div{
color:#000;
a{
color:#333;
}
}编译后:
div {
color: #000;
}
div a {
color: #333;
}
Sass的相关应用
- 使用 $ 定义变量

- 支持运算符 :+ - * / %

- 注释支持:// 单行注释不会被编译、/**/ 多行注释会被编译
- 条件判断 :@if @else

- 伪类选择器:&:hover,需要加&表示自身
//伪类
#content {
color: yellow;
&:hover {
color: palevioletred;
}
}
// 编译后
#content {
color: yellow;
}
#content:hover {
color: palevioletred;
}
- 函数
- @function 定义函数
- @return 返回对应的内容
- 循环
- @for 从某个值到某个值:@for 变量 from 1 to 5
- @while :@while 变量 > 0
- @each 相当于forEach:@each 变量 in 数组

- 混入器:用于设置对应的内容
- @mixin 定义混入器
- @include 引入混入器
// 混入器的使用
@mixin a {
background: red;
}
@mixin border($size, $style, $color) {
border: $size $style $color;
}
@mixin shadow($offsetleft:10px, $offsettop:20px, $width:30px, $color:green) {
box-shadow: $offsetleft $offsettop $width $color;
}
div {
font-size: 18px;
@include a();
@include border(1px, solid, red);
@include shadow()
}
// 编译后
div {
font-size: 18px;
background: red;
border: 1px solid red;
box-shadow: 10px 20px 30px green;
}
- 模块化:@import 省略后缀名 (css文件还是sass文件还是scss都能省略后缀名),无需导出,因为默认导出。
@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);
- 继承:@extend

文章介绍了前端路由的三种模式:页面路由、hash路由和history路由,重点讲解了SPA(单页应用程序)和SSR(服务器渲染)的应用场景和优缺点。在Vue中展示了hash路由的实现,并给出了自定义模拟hash和history路由的示例。此外,还提到了Sass作为一种预编译CSS的工具,其特性与Less的区别。

2256

被折叠的 条评论
为什么被折叠?



