js的27天(SPA路由实现及SASS)

路由


前端路由

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

前端的分类

页面路由(刷新)

根据对应的地址访问不同的页面(

location.href

location.assign

location.repalce)

hash路由(不会刷新)

根据对应的hash地址来渲染不同的内容(onhashchange)

location.hash 来获取对应的hash值 通过onhashchange进行监听

history路由(不会刷新)

根据对应的history页面的地址来渲染不同的内容(onpopstate)

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

通过history.back history.go history.forward来触发对应的onpopstate事件

后端路由

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

SPA


单页应用程序 (single page application),整一个应用只有一个页面,那么对应的页面调整就没有意义了,所以对应的SPA的路由实现就主要是hash模式和history模式。在后续的vue或者是对应的react中,他主要做的是SPA的应用那么对应的主要采用的模式hash和history,hash的监听能直接触发而history的监听不能直接触发,所以默认的模式就是hash模式。

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 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({

            //路由配置 router 名词(路由对象)  route 动词(路由配置) routes 多个(路由配置)

            routes:[

                //route规则

                {

                    name:'home',//名字

                    path:'/', //路由地址

                    component:home //组件 渲染什么

                },

                {

                    name:'user',

                    path:'/user',

                    component:user

                }

            ]

        });

        new Vue({

            el:'#app',

            //传入路由配置 router

            router

        })

    </script>

</body>

</html>

hash模式路由实现

根据对应hash值的变化来控制对应渲染内容的变化(onhashchange)

classVueRouter{

constructor(option) {

//获取传入的配置

this.routes=option['routes']

this.handlerLoad()

   }

//处理hash改变的监听 需要渲染的元素

obServer(element) {

this.el=element

window.onhashchange=()=>{

this.render()

       }

   }

//渲染的方法

render() {

let_this=this

//获取当前hash值 去除#

lethash=location.hash.slice(1)

//去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

letlinkList=this.el.querySelectorAll('router-link')

Array.from(linkList).forEach(link=>{

//找到对应的to属性

letpath=link.getAttribute('to')

//创建a标签 将他的to地址赋值href属性

leta=document.createElement('a')

a.href="#"+path

a.innerHTML=link.innerHTML

_this.el.replaceChild(a,link)

       })

   }

//在打开的时候前面自动+#/

handlerLoad(){

window.onload=()=>{

location.hash='/'

       }

   }

}

classVue{

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 路径变化(location.pathname)

class VueRouter {

    constructor(option) {

        //获取传入的路由配置

        this.routes = option.routes

    }

    obServer(element) {

        //需要挂载的el对象

        this.el = element

        //监听onpopstate事件

        window.onpopstate = () => {

            //读取path根据路径匹配渲染不同的内容

            this.render(location.pathname)

        }

    }

    render(path) {

        let _this = this

        //匹配

        // 遍历路由配置

        this.routes.forEach(route => {

            //判断对应的path地址是否等于route的path地址

            if (path == route.path) {

                //渲染

                let view = _this.el.querySelector('router-view')

                view.innerHTML = route.component.template

            }

        });

    }

    handlerLoad() {

        window.onload = () => {

            //替换当前路径

            history.replaceState('', '', './')

            //第一次渲染

            this.render('/')

        }

    }

    hanlderLink() {

        let _this = this

        let list = []

        //获取所有的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)

            list.push(a)

        })

        //给a添加点击事件

        //获取所有的a list

        list.forEach(a => {

            a.addEventListener('click', function (e) {

                e = e || window.event

                //禁止a默认行为

                e.preventDefault();

                history.pushState('', '', a.href)

                //渲染

                _this.render(location.pathname)

            })

        })

    }

}

class Vue {

    constructor(option) {

        this.el = document.querySelector(option.el)

        this.router = option.router

        //监听传入当前的el元素

        this.router.obServer(this.el)

        this.router.handlerLoad()

        this.router.hanlderLink()

    }

}

Sass


概述

sass是一个预编译的css,核心还是css(css语法它都支持),他最终还是会编译成css,sass的好处在于它可以以js的方式书写css(有跟js原生一样的语法)。跟他同类的预编译的css还有less以及stylus等。sass它是使用ruby语言书写的,后续使用的python所以sass必须具备python环境。sass它和less是一类的产品,但是俩种的书写语言不一样。

官方文档

使用方式

使用node来进行sass的编译

npm i sass -D

sass sass文件名 文件名(css文件名)

使用第三方插件来进行编译

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

easy sass的扩展配置

sass的俩种扩展名

.sass 以缩进作为区分 (里面是没有;没有{})

div

    color:red

    p

        font-size:13px

.scss 跟正常的css一样

div{

    background-color: red;

}

sass的相关应用

变量定义 ($变量名:值) *

$color:red;

div{

    background-color:$color

}

编译

div {

  background-color: red;

}

支持运算符(+ - * / %) *

$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;

        }

    }

}

编译

.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: red;

    }

    @else{

        color: green;

    }

}

编译

.item {

  color: green;

}

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 (for each遍历)

$list:1,2,3,4;

@each $item in $list {

    .item_list_#{$item}{

        width: $item;

    }

}

函数

@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()

}

注释

//我是注释 不会显示

/*我是注释 会显示*/

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、Web端 https://www.nowcoder.com/discuss/588372 1.float如何清...
    陈一季阅读 4,529评论 2 18
  • 一、初始Vue-Cli 1. 安装 npm install -g @vue/cli # OR yarn globa...
    野鸽儿阅读 527评论 0 0
  • # Vue.js - day01 ## 插件安装推荐 vscode有二个常用插件:vetur,Vue 2 Snip...
    wuyuan0127阅读 636评论 0 0
  • 基本信息 es6中const定义的属性是否可以改变? 可以的,为什么会这样呢?这是由于对象或者数组属于引用数据类。...
    习惯就好a阅读 8,635评论 0 1
  • 相关概念 混合开发和前后端分离 混合开发(服务器端渲染) 前后端分离后端提供接口,前端开发界面效果(专注于用户的交...
    他爱在黑暗中漫游阅读 2,907评论 4 45