day27 SPA路由实现及SASS讲解

路由分为前端路由和后端路由

前端路由 :

根据对应的路由地址来渲染不同的内容

前端的分类 :

页面路由 ( 一定会刷新)

  • 是根据对应的地址访问不同的页面 (location.href , location.assign , location.replace)

hash路由 ( 不会刷新 )

  • 是根据对应的hash地址来渲染不同的内容

  • location.hash可以获取对应的hash值 , 通过onhashchange事件来进行监听

history路由 ( 不会刷新 , 地址会改变 )

  • 根据对应histrory页面的地址来渲染不同的内容 ( onpopstate事件来监听 )

  • 通过replaceState和pushState来改变state值和页面的地址

  • 通过history.back , history.go , history.forward 来触发onpopstate事件

后端路由 :

根据对应的路由地址访问对应的接口

SPA

是单页应用程序 ( single page application ),简单来说就是整个应用只有一个页面 , 那么页面调整就没有意义了也不需要刷新页面 , 所以SPA的路由实现主要是hash模式和history模式 。在vue和react中,SAP的应用主要采用的模式是hash和history,默认是hash模式,hash的监听能直接触发,而history的监听不能直接触发

Vue中的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="./lib/vue.min.js"></script>
    <script src="./lib/vue-router.js"></script>
</head>
<body>
    <div class="box">
        <!-- 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({
            // 路由配置:router是名词(配置对象),route是动词(路由配置),routes也是动词(多个路由配置)
            routes: [
                {
                    name: 'home',//名字
                    path: '/',//路径
                    component: home //需渲染的内容
                }, {
                    name: 'user',
                    path: '/user',
                    component: user
                }
            ]
        })
        new Vue({
            el: '.box',
            //传入路由配置router
            router
        })
    </script>
</body>
</html>
复制代码
hash模式路由实现

根据hash值的变化来渲染内容(使用onhashchange事件)

复制代码
class VueRouter {
    constructor(option) {
        //获取传入的配置
        this.routes = option['routes']
        this.handlerLoad()
    }
    //处理hash改变的监听 需要渲染的元素
    obServer(element) {
        this.el = element
        window.onhashchange = () => {
            this.render()
        }
    }
    render() {
        let _this = this
        //获取当前hash值 去除#
        let hash = location.hash.slice(1)
        //当前hash值和this.routes比较,相同就渲染
        this.routes.forEach(route => {
            if (hash == route.path) {
                _this.el.querySelector('router-view').innerHTML = route.component.template
            }
        });
    }
    //a标签变化
    handlerLink() {
        let _this = this
        //获取所有的router-link
        let linkList = this.el.querySelectorAll('router-link')
        Array.from(linkList).forEach(link => {
            //找到对应的to属性
            let path = link.getAttribute('to')
            //创建a标签 将他的to地址赋值href属性
            let a = document.createElement('a')
            a.href = "#" + path
            a.innerHTML = link.innerHTML
            _this.el.replaceChild(a, link)
        })
    }
    //在打开的时候前面自动+#/
    handlerLoad() {
        window.onload = () => {
            location.hash = '/'
        }
    }
}
class Vue {
    constructor(option) {
        this.el = document.querySelector(option.el)
        this.router = option.router
        this.router.obServer(this.el)
        //第一次渲染
        this.router.render()
        this.router.handlerLink()
    }
}
复制代码
history模式

核心点就是使用onpopstate事件监听path路径的变化来进行渲染(location.pathname)

复制代码
class VueRouter {
    constructor(option) {
        this.routes = option['routes']
    }
    //监听path的变化
    obServer(element) {
        this.el = element
        window.onpopstate = () => {
            //渲染(传个路径)
            this.render(location.pathname)
        }
    }
    //渲染的方法
    render(path) {
        let self = this
        console.log(this.routes);
        //遍历路由配置并判断路径是否相同,相同就渲染到页面上
        this.routes.forEach((route) => {
            if (path == route.path) {
                self.el.querySelector('router-view').innerHTML = route.component.template
            }
        })
    }
    //浏览器加载就替换 replaceState是替换url地址
    handlerLoad() {
        window.onload = () => {
            history.replaceState('', '', './')
        }
    }
    handlerLink() {
        let self = this
        let list = []
        //获取页面上的router-link并通过遍历给每个标签添加a标签和 href属性
        let linkList = this.el.querySelectorAll('router-link')
        Array.from(linkList).forEach((link) => {
            let path = link.getAttribute('to')
            let a = document.createElement('a')
            a.href = path
            //
            a.innerHTML = link.innerHTML
            self.el.replaceChild(a, link)
            list.push(a)
        })
        list.forEach((a) => {
            //给所有的a设置点击事件并禁止默认跳转行为
            a.addEventListener('click', function (e) {
                e = e || window.event
                e.preventDefault()
                history.pushState('', '', a.href)
                //渲染
                self.render(location.pathname)
            })
        })
    }
}

class Vue {
    constructor(option) {
        this.el = document.querySelector(option.el)
        this.router = option.router
        this.router.obServer(this.el)
        // this.router.render('/')
        this.router.handlerLoad()
        this.router.handlerLink()
    }
}
复制代码

Sass

概述 :

sass是一个预编译的css , 核心是css ( css语法它都支持 ) , 然后它最终还是会编译成css , 它是使用ruby语言书写的 , 后续使用的是ptython 所以sass必须具备Python环境

好处在于可以以js的方式来书写css样式 ( 有跟js原生一样的语法 )

跟他同类的预编译css的 还有less , 以及stylus 等

它和less是一类产品 , 但是两种的书写语言不一样

使用方式
  • 使用node来进行sass的编译

npm i sass -D (安装)
sass文件名 编译后的sass文件名
  • 使用第三方插件来进行编译

vscode的第三方插件 easy sass , sass , live sass

easy sass的扩展配置

sass的两种扩展名
  • .sass 以缩进作为区分 ( 里面是没有 ; 和{} )

div
    color:red
    p
        font-size:14px
  • .scss 跟正常的css一样
div{
    background-color:red;
}

sass的相关应用

  • 变量定义 ( $变量名 : 值 )
$color:red;
$font-size:14px;
div{
    color:$color
        p{
            font-size:$font-size
    }
}

编译

div{
    color:red;
}
p{
    font-size:14px
}
  • 支持运算符 ( + - * / % ) *
$size:12px;
p{
    font-size:$size%100;
    width:$size*10-100;
    height:$size+100
}

编译

p{
    font-size:12px;
    width:20px;
    height:112px
}
  • 样式关系
复制代码
span,img{
    padding:10px;
}
.box{
    background-color:red;
    img{
        width:100px;
        h1{
            height:100px
        }
    }
}
#content{
    color:yellow;
    &:hover{
        color:green;
    }
}
.box{
    font-size:12px;
    &:hover{
        font-size:18px
    }
}
复制代码

编译

复制代码
span{
    padding:10px;
}
img{
    padding:10px;
}
.box{
    background-color:red;
}
.box img{
    width:100px;
}
.box img h1{
    height:100px;
}
#content{
    color:yellow;
}
#content:hover{
    color:green;
}
#content .box{
    font-size:12px;
}
#content .box:hover{
    font-size:18px;
}
复制代码
  • 插值表达式
#{变量名}:获取对应的变量值
  • if判断
$number:10;
.item{
    @if $number>=10{
        color:hotpink;
    }@else{
        color:green;
    }
}

编译

.item{
    color:hotpink;
}
  • for循环 ( while循环 )
@for $i from 0 to 3{
    .item_#{$i}{
        size:$i
    }
}

编译

复制代码
.item_0 {
  size: 0;
}

.item_1 {
  size: 1;
}

.item_2 {
  size: 2;
}
复制代码
  • each (forEach遍历)
$list:1,2,3,4; //声明数组
@each $item in $list{
    .item_list_#{$item}{
        width:$item;
    }
}

编译

复制代码
.item_list_1 {
  width: 1;
}

.item_list_2 {
  width: 2;
}

.item_list_3 {
  width: 3;
}

.item_list_4 {
  width: 4;
}
复制代码
  • 函数
@function f($arg:20px){
    @return $arg+10
}
div{
    height:f(10px);
    width:f()
}

编译

div{
    height:20px;
    width:30px;
}
  • 混入器
复制代码
@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 './test.scss';
div{
    @include shadow
}
posted @   邱你咋滴  阅读(70)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示