首页 > 其他分享 > day 26 Promise的回顾及SPA路由实现

day 26 Promise的回顾及SPA路由实现

时间:2022-08-30 19:45:04浏览次数:73  
标签:26 hash Promise router SPA path let 对应 路由

Promise

return 在对应的promise的函数中

在promise里面的then函数(catch函数中)return相当于调用resolve 。 throw new Error相当于调用reject

Promise.resolve('第一个值').then((res) => {
    console.log(res)
    return '第二个值' //resolve
}).then(res => {
    console.log(res)
})
Promise.resolve('第一个值').then((res) => {
    console.log(res)
    throw new Error('异常') //reject
}).catch(err => {
    console.log(err)
})

 

then函数里面传递俩个参数(then和catch里面参数为函数)



Promise.reject()
    .then(function success1 (res) {
    console.log('成功');//抛异常
}, function fn (e) { //处理错误的函数 不会处理前面的函数抛出的错误
    console.error('错误') //相当于同级的catch
})

 

如果对应的then或者catch里面的参数不是函数那么就会发生值穿透


Promise.resolve('我是值')
    .then(1)
    .then(2)
    .then(3)
    .then(console.log) //===> .then(res=>console.log(res))

 

setImmediate 立即执行(没事做先执行你)

他也是一个宏任务 而且他这个宏任务只排在setTimeout之前

nextTick (类似于setTimeout 宏任务 又是一个微任务 (他可以是宏任务也可以微任务))

当你没有进行dom操作的时候 (没有进行插入或渲染)他是一个微任务

反之他就是一个宏任务(也就是说它需要等待dom完成相关操作以后才执行)

路由实现

路由概念

前端路由:根据对应的请求地址渲染对应的组件(页面)

根据BOM里面的history和location对象实现(前端路由分俩种模式 hash模式 history模式)

后端路由:根据对应的请求地址和请求方式来访问对应的接口(restful风格接口)

前端路由

前端路由的俩种实现方式

hash模式的原理

通过监听location.hash的变化 来控制对应的渲染变化(onhashchange)

history模式的原理

通过监听对应的state的变化 来控制对应的渲染变化 (onpopstate)

pushstate 添加state数据 同时会改变对应的url路径

replacestate 替换state的数据 同时将对应的路径替换为对应的路径

onpopstate事件 必须利用history.back history.go history.forward

单页应用

前面提到了对应的hash模式或者是history模式都不会进行页面的跳转(不会进行刷新操作)也就是说对应的页面不能进行跳转也就意味着对应的页面只有一个。只有一个页面的应用(SPA 单页应用)

基于单页应用实现路由

hash模式实现代码
// 利用hash实现的路由
class Router {
    constructor() {
        //路由配置存储的列表 地址 渲染什么
        this.routes = []
    }
    add(path, commponent) { //添加路由配置 path表示对应的路由路径 commponent表示需要渲染的内容
        this.routes.push({
            path,
            commponent
        })
    }
    listener(el) { //监听函数 监听对应的hash变化的 做对应的处理 el表示你需要渲染的内容
        window.onhashchange = this.hashChange(el)
        this.hashChange(el)() //第一次需要调用
    }
    hashChange(el) {
        let that = this
        return function () {
            //location.hash
            let hash = location.hash //获取当前的hash值
            //把第一个#删除
            hash = hash.substring(1)
            //根据获取的hash值取数组里面匹配出来
            that.routes.forEach(route => {
                if (route.path == hash) { //匹配出来了
                    //进行相关的渲染
                    el.innerHTML = route.commponent()
                }
            })
        }
    }
}
let router = new Router()
//先添加对应的地址
router.add('/', function () {
    return '<h1>我是主页</h1>'
})
router.add('/list', function () {
    return '<h1>我是列表页</h1>'
})
router.add('/user', function () {
    return '<h1>我是用户页</h1>'
})
//打开页面就加#
window.onload = () => {
    //获取router-view
    let view = document.querySelector('router-view')
    //跟对应的name存在关系
    let path = view.getAttribute('name')
    let box = document.createElement('div')
    document.querySelector('#app').replaceChild(box, view)
    // 判断是否存在#
    if (!location.href.includes('#')) {
        location.href += '#' + path
    }
    //做渲染
    //监听调用
    router.listener(box)
}

 


html代码


<!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>单页应用的主页</title>
</head>
<body>
    <div id="app">
        <!-- vue里面显示路由视图的标签 name里面填写是地址 -->
        <router-view name="/"></router-view>
    </div>
    <script src="./hash.js"></script>
</body>
</html>

 

history模式


// 利用history实现的路由
class Router {
    constructor() {
        this.routes = [] //存储对应的路由配置
        this.callback
    }
    add(path, commponent) { //添加的方法
        this.routes.push({
            path,
            commponent
        })
    }
    listener(callback) { //传递一个函数 专门用于渲染
        this.callback = callback
        history.pushState('/','','/') //第一次进入/
        this.render()
        window.onpopstate = () => {
            this.render()
        }
    }
    render() {
        let that = this
        //获取对应的路径地址
        let path = location.pathname
        //比对 拿对应的routes去进行遍历比对
        this.routes.forEach(route => {
            if (route.path == path) {
                // 进行渲染
                that.callback(route.commponent())
            }
        });
    }
}
//构建一个路由对象
let router = new Router()
router.add('/', () => '<h1>主页</h1>')
router.add('/user', () => '<h1>用户页</h1>')
router.add('/list', () => '<h1>列表页</h1>')
router.listener(renderHtml => {
    //获取router-view
    let view = document.querySelector('router-view')
    view.innerHTML = renderHtml
})
//获取所有的router-link 变成a标签
let links = document.querySelectorAll('router-link')
//保存所有的创建的a
let aArr = []
//读取对应的属性 需要遍历
Array.from(links).forEach(link => {
    //获取to属性加给对应的a的href
    //创建a标签替换对应的router-link
    let a = document.createElement('a')
    a.href = link.getAttribute('to')
    a.innerHTML = link.innerHTML //将link的内容拿出赋值给对应的a
    document.querySelector('#app').replaceChild(a, link)
    aArr.push(a)
})
//给a添加点击事件
aArr.forEach(a => {
    a.onclick = function (e) {
        e.preventDefault(); //禁止a的默认事件
        //点击的时候 pushState加东西
        history.pushState(this.href, '', this.href)
        //重新渲染
        router.render()
    }
})

 

html代码


<!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>
</head>
<body>
    <div id="app">
        <!-- 改成a标签 -->
        <router-link to="/">主页</router-link>
        <router-link to="/user">用户页</router-link>
        <router-link to="/list">列表页</router-link>
        <router-view name="path"></router-view>
    </div>
    <script src="./histroy.js"></script>
</body>
</html>
 

 

标签:26,hash,Promise,router,SPA,path,let,对应,路由
From: https://www.cnblogs.com/jxooooolxe/p/16640567.html

相关文章

  • 深入浅出promise、await和async以及Generator系列——promise的基本语法和使用
    深入浅出promise、await和async以及Generatorpromise的语法promise的语法是es6比较复杂的一个语法,所以请耐心看完promise是面向对象思想实现的,使用的第一步需要创建一......
  • P3426 [POI2005]SZA-Template
    对于字符串刻印章,使每个字符都能被印出来,并且不能印上其他字符。求印章最短长度。\(|S|\leq5\times10^5\)。看到题目第一感觉是KMP,但具体实现很费脑筋。先举个例子:......
  • AtCoder Beginner Contest 266 一句话题解
    AandBsbt,不讲。C垃圾计算几何,问是不是一个凸包,搞份板子交就可以了。D简单dp,令\(f(i,j)\)表示第\(i\)个时间在第\(j\)个位置的最大价值,从上一个时间转移,可以......
  • ABC266 Ex - Snuke Panic (2D)
    ABC266Ex-SnukePanic(2D)挺好的一道题(不过调了好久QAQ方法一比较暴力的做法。首先,你容易想到一个DP状态:\(f(t,x,y)\)表示在\(t\)时刻到达\((x,y)\)的最......
  • NC235267 星球大战
    题目原题地址:星球大战题目编号:NC235267题目类型:map、list时间限制:C/C++2秒,其他语言4秒空间限制:C/C++262144K,其他语言524288K1.题目大意二维平面上n个坐标对应......
  • spark中各个技术点中的依赖
    1.sparkcore<dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.11</artifactId><version>2.3.1</version>2.sparksql需要引入j......
  • ABC265F,G
    ABC265F题解做法byMikukuovo#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintmod=998244353;intn,d;intmain(){ios::sync_wit......
  • AtCoder Beginner Contest 266
    比赛链接:https://atcoder.jp/contests/abc266C-ConvexQuadrilateral题意:平面图上有一个四边形,按照逆时针顺序给定四个点的坐标,判断四边形是不是凸的。思路:求两条......
  • 【2022.8.26】前端开发(5)
    学习内容概要JS获取用户输入值JS事件绑定jQuery类库jQuery常见操作内容详细JS获取用户输入普通数据(输入、选择) 标签对象.value文件数据(上传) 标签对象.......
  • AtCoder Beginner Contest 265(D-E)
    D-IrohaandHaiku(NewABCEdition)题意:找一个最少含有三个点的区间,将区间分成三块,三块的和分别为p,q,r,问是否存在这样的区间题解:先预处理一遍前缀和,和每一个前缀......