精华内容
下载资源
问答
  • 1. 需求如果要你实现个前端路由,应该如何实现浏览器的前进后退 ?2. 问题首先浏览器中主要有这几个限制,让前端不能随意的操作浏览器的浏览纪录:•没有提供监听前进后退的事件。•不允许开发者读取浏览纪录,...

    1. 需求

    如果要你实现一个前端路由,应该如何实现浏览器的前进与后退 ?

    2. 问题

    首先浏览器中主要有这几个限制,让前端不能随意的操作浏览器的浏览纪录:

    •没有提供监听前进后退的事件。•不允许开发者读取浏览纪录,也就是 js 读取不了浏览纪录。•用户可以手动输入地址,或使用浏览器提供的前进后退来改变 url。

    所以要实现一个自定义路由,解决方案是自己维护一份路由历史的记录,从而区分 前进、刷新、回退。

    下面介绍具体的方法。

    3. 方法

    目前笔者知道的方法有两种,一种是 在数组后面进行增加与删除,另外一种是 利用栈的后进先出原理。

    我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我并添加我的web前端交流裙【六零零】+【六一零】+【一五一】,即可免费获取。

    3.1 在数组最后进行 增加与删除

    通过监听路由的变化事件 hashchange,与路由的第一次加载事件 load ,判断如下情况:

    •url 存在于浏览记录中即为后退,后退时,把当前路由后面的浏览记录删除。•url 不存在于浏览记录中即为前进,前进时,往数组里面 push 当前的路由。•url 在浏览记录的末端即为刷新,刷新时,不对路由数组做任何操作。

    另外,应用的路由路径中可能允许相同的路由出现多次(例如 A -> B -> A),所以给每个路由添加一个 key 值来区分相同路由的不同实例。

    注意:这个浏览记录需要存储在 sessionStorage 中,这样用户刷新后浏览记录也可以恢复。

    笔者之前实现的 用原生 js 实现的轻量级路由 ,就是用这种方法实现的,具体代码如下:

    // 路由构造函数function Router() { this.routes = {}; //保存注册的所有路由 this.routerViewId = "#routerView"; // 路由挂载点 this.stackPages = true; // 多级页面缓存 this.history = []; // 路由历史} Router.prototype = { init: function(config) { var self = this; //页面首次加载 匹配路由 window.addEventListener('load', function(event) { // console.log('load', event); self.historyChange(event) }, false) //路由切换 window.addEventListener('hashchange', function(event) { // console.log('hashchange', event); self.historyChange(event) }, false) }, // 路由历史纪录变化 historyChange: function(event) { var currentHash = util.getParamsUrl(); var nameStr = "router-history" this.history = window.sessionStorage[nameStr] ? JSON.parse(window.sessionStorage[nameStr]) : [] var back = false, // 后退 refresh = false, // 刷新 forward = false, // 前进 index = 0, len = this.history.length; // 比较当前路由的状态,得出是后退、前进、刷新的状态。 for (var i = 0; i < len; i++) { var h = this.history[i]; if (h.hash === currentHash.path && h.key === currentHash.query.key) { index = i if (i === len - 1) { refresh = true } else { back = true } break; } else { forward = true } } if (back) { // 后退,把历史纪录的最后一项删除 this.historyFlag = 'back' this.history.length = index + 1 } else if (refresh) { // 刷新,不做其他操作 this.historyFlag = 'refresh' } else { // 前进,添加一条历史纪录 this.historyFlag = 'forward' var item = { key: currentHash.query.key, hash: currentHash.path, query: currentHash.query } this.history.push(item) } // 如果不需要页面缓存功能,每次都是刷新操作 if (!this.stackPages) { this.historyFlag = 'forward' } window.sessionStorage[nameStr] = JSON.stringify(this.history) }, }

    3.2 利用栈的 后进者先出,先进者后出 原理

    在说第二个方法之前,先来弄明白栈的定义与后进者先出,先进者后出原理。

    3.2.1 定义

    栈的特点:后进者先出,先进者后出。

    举一个生活中的例子说明:就是一摞叠在一起的盘子。我们平时放盘子的时候,都是从下往上一个一个放;取的时候,我们也是从上往下一个一个地依次取,不能从中间任意抽出。

    d8e2bc0e35039e4b3b0a1b21ebb3681a.png

    因为栈的后进者先出,先进者后出的特点,所以只能栈一端进行插入和删除操作。这也和第一个方法的原理有异曲同工之妙。

    下面用 JavaScript 来实现一个顺序栈:

    // 基于数组实现的顺序栈class ArrayStack { constructor(n) { this.items = []; // 数组 this.count = 0; // 栈中元素个数 this.n = n; // 栈的大小 } // 入栈操作 push(item) { // 数组空间不够了,直接返回 false,入栈失败。 if (this.count === this.n) return false; // 将 item 放到下标为 count 的位置,并且 count 加一 this.items[this.count] = item; ++this.count; return true; } // 出栈操作 pop() { // 栈为空,则直接返回 null if (this.count == 0) return null; // 返回下标为 count-1 的数组元素,并且栈中元素个数 count 减一 let tmp = items[this.count-1]; --this.count; return tmp; }}

    其实 JavaScript 中,数组是自动扩容的,并不需要指定数组的大小,也就是栈的大小 n 可以不指定的。

    3.2.2 应用

    栈的经典应用: 函数调用栈

    操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构, 用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。为了让你更好地理解,我们一块来看下这段代码的执行过程。

    function add(x, y) { let sum = 0; sum = x + y; return sum;} function main() { let a = 1; let ret = 0; let res = 0; ret = add(3, 5); res = a + ret; console.log("res: ", res); reuturn 0;}

    上面代码也很简单,就是执行 main 函数求和,main 函数里面又调用了 add 函数,先调用的先进入栈。

    执行过程如下:

    d8cd68a3665a327c8bc0872b5ccc4d0f.png

    3.2.3 实现浏览器的前进、后退

    第二个方法就是:用两个栈实现浏览器的前进、后退功能。

    我们使用两个栈,X 和 Y,我们把首次浏览的页面依次压入栈 X,当点击后退按钮时,再依次从栈 X 中出栈,并将出栈的数据依次放入栈 Y。当我们点击前进按钮时,我们依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,那就说明没有页面可以继续后退浏览了。当栈 Y 中没有数据,那就说明没有页面可以点击前进按钮浏览了。

    比如你顺序查看了 a,b,c 三个页面,我们就依次把 a,b,c 压入栈,这个时候,两个栈的数据如下:

    7300b6767196673eef761851db633f53.png

    当你通过浏览器的后退按钮,从页面 c 后退到页面 a 之后,我们就依次把 c 和 b 从栈 X 中弹出,并且依次放入到栈 Y。这个时候,两个栈的数据就是这个样子:

    d270a84889308e394376a68d33d92d7c.png

    这个时候你又想看页面 b,于是你又点击前进按钮回到 b 页面,我们就把 b 再从栈 Y 中出栈,放入栈 X 中。此时两个栈的数据是这个样子:

    91388e54893b08ccb224a989807572f0.png

    这个时候,你通过页面 b 又跳转到新的页面 d 了,页面 c 就无法再通过前进、后退按钮重复查看了,所以需要清空栈 Y。此时两个栈的数据这个样子:

    14bfd5835ead833400485f33e233f411.png

    如果用代码来实现,会是怎样的呢 ?各位可以想一下。

    其实就是在第一个方法的代码里面, 添加多一份路由历史纪录的数组即可,对这两份历史纪录的操作如上面示例图所示即可,也就是对数组的增加和删除操作而已, 这里就不展开了。

    其中第二个方法与参考了 王争老师的 数据结构与算法之美。

    展开全文
  • 不论飞机还是船舶,控制杆前推总是加速、后拉是减速,这样似乎才符合前进后退的方向。但是普通人并不具备这种意识,同时汽车相比船舶的行驶速度要快太多,如果这样设计则必然会带来安全隐患——加速时有没有感觉人...

    2

    原因_安全考虑自动挡档位设计是否有些「反人类」,前推不是前进反而是倒退,后拉不倒车是为什么呢?

    对于驾驶意识足够强的赛车手而言,这种设计确实是相当的别扭。不论飞机还是船舶,控制杆前推总是加速、后拉是减速,这样似乎才符合前进后退的方向。但是普通人并不具备这种意识,同时汽车相比船舶的行驶速度也要快太多,如果这样设计则必然会带来安全隐患——加速时有没有感觉人在倒退呢?

    知识点

    1:加速G力。汽车在加速过程中驾乘人员会感受到“推背感”,这种感觉就是所谓的G力。加速过程中产生的相互作用力会让人们难以做出往前的动作,下意识的反应是拉紧什么来降低后移的速度与程度。

    只有自动挡驾驶经验的司机往往会在挂挡后拉紧方向盘,而有手动挡汽车驾驶经历的用户则习惯于拉住档杆。此时如果档杆按照“PNDRM/S/L”设计的话,加速中就有可能直接拉到R挡(倒挡)上;纯机械结构且智能化程度不高的自动变速箱是有可能结合倒挡的,此处是车辆虽然不至于直接倒车,但齿轮箱也基本要报废了。

    2:刹车时是一种怎样的状态?汽车刹车过程中人会前倾,因为驾乘人员与行驶中的车辆已经“集成于一体”,车辆移动的惯性作用力同样会作用于乘员!刹车过程中驾乘人员仍然受到前进的作用力影响,所以状态为车辆加速但人没有减速——除非依靠与座椅的摩擦力和安全带的约束力才能稳稳的坐在车上。

    此时如果自动变速箱设计为「PNDRL」,刹车时则有可能将档位推到P挡,结果则会是驻车棘爪与棘轮的可能结合导致结构断裂。那么就不能给“P/R”两个档位设计锁止结构吗?答案自然是可以的,只是这样的设计会有较高的制造成本,而且仍然不符合加速控制的正常驾驶习惯,所以不如设计成【PRND/M】。

    可能出现的变化PRNDMSL的设计符合加减速的姿态需要,然而在智能汽车的阶段似乎是可以改变的。

    参考电子档杆,不论是档把还是旋钮,在错误操作时TCU控制单元都不会执行。比如行驶中挂倒挡和P挡都会直接跳到空挡,这就保证了错误操作也会安全。而随着汽车性能一步步的提升,尤其是在电驱时代动力出现了指数级的增长;普通汽车用户也在逐渐追求驾驶的乐趣,那么参考M挡的设计,一旦用户养成习惯则传统机械档位设计反而成为了麻烦。

    M_manual手动控制模式,其加挡是往前推、减档是往后拉;在这一模式中控制车辆会感觉更加的游刃有余,而且符合专注驾驶性能车的状态中的逻辑思维。所以在智能变速箱时代完全可以设计为「DNRP」模式,M挡可以直接取消,按照以下标准设计也许会更有意思。D1_正常驾驶模式

    D2_前进2

    D3_前进3

    至于「前进4」就不用设计了,超大G力一般人是接受不了的。耐心等待一段时间吧,目前已经有车企在这么设计了,只是何时量产目前还不能确定。(猜猜是哪家)

    编辑:天和Auto

    内容:原创发布

    欢迎留言讨论,保留版权保护权利

    展开全文
  • 客户不知道刚才滑动到哪里了,忘记了选择哪个商品,得要重新滑到下面,如果这时候我们做个缓存体验就比较好。如果页面全部用keep-alive那肯定不行,因为客户返回上个页面选择个商品的时候再跳到详情页,...

    有时候我们在开发的时候会遇到一个需求:

             我在home页面选择了一个分类跳到about页面的时候根据home页面转过来的分类数据加载一些商品数据,之后选择了一个商品又跳到detail详情页面,这时客户是选错了想返回上一个页面的重新选择,但是about页面重新加载了数据和页面,客户不知道刚才滑动到哪里了,也忘记了选择哪一个商品,得要重新滑到下面,如果这时候我们做一个缓存体验就比较好。如果页面全部用keep-alive那肯定不行,因为客户返回上一个页面选择一个商品的时候再跳到详情页,keep-alive保存的信息是之前选择过的商品,这样就要刷新。

    现在我就要实现这样的一个功能:

           页面前进都刷新,而某后退某一个页面不刷新,如:有三个页面home、about、detail,跳转顺序是home->about->detail,从home跳到about刷新,从detail后退回到about不刷新。看下图

     

     

    上面两种情况:

    第一种:把路由keepAlive全部设为false,

    第一种:把路由keepAlive全部设为true

    路由:

     App.vue初始化页面

     store.js

     

     或者可以不用store:

    home,about,detail页面都是一样的

     

    =================================================

        付费解决前端问题:

     

    展开全文
  • 使用栈实现浏览器的前进后退当你次访问 1、2、3 页面之后,点击浏览器的后退按钮就可以返回到 2 和 1.当后退到 1,点击前进按钮还可以继续查看页面 2、3。但是当你退到 2 页面,点击了新的页面 4,那就无法继续...

    使用栈实现浏览器的前进后退

    当你一次访问 1、2、3 页面之后,点击浏览器的后退按钮就可以返回到 2 和 1.当后退到 1,点击前进按钮还可以继续查看页面 2、3。但是当你退到 2 页面,点击了新的页面 4,那就无法继续通过前进、后退查看页面 3 了。

    「我们如何实现这个功能呢?」

    什么是栈

    「栈」我们都知道 Java 虚拟机 JVM 就有『本地方法栈』『虚拟机栈』的划分,每个方法执行的时候都会创建一个栈帧用于存放局部变量表、操作数栈、动态链接、方法出口信息。

    每一个方法从调用到结束,就对应着一个栈帧在「虚拟机栈」的入栈与出栈的过程。这里其实就是运用了「栈」数据结构的特性:「后进先出、先进后出」。就像一摞叠在一起的盘子,入栈就像我们放盘子,出栈就是我们从上往下一个个取。

    693489a5a9575074a2a842e29539dcc6.png

    「栈是一种「操作受限」的线性表」,只允许在一端插入和删除数据。

    是不是觉得这种数据结构有何意义,只有受限的操作,相比「数组」和「链表」感觉没有任何优势。为何还要用这个「操作受限」的「栈」呢?

    特定的数据结构用在特定的场景,数组与链表暴露太多的操作接口,操作灵活带来的就是不可控,也就更加容易出错。

    「当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构」。

    比如我们的 JVM 栈结构,方法调用则是对应的入栈与出栈。

    栈的实现

    核心操作就是「入栈」「出栈」,也就是在栈顶插入元素、从栈顶取出元素。

    理解了两个核心操作后,我们可以使用数组或者链表来实现。

    数组实现的栈,叫做 「顺序栈」 。

    用链表实现,叫做 「链式栈」。

    这里我通过数组实现一个顺序栈,可用于实际开发中,我拓展了「清空栈」、「拓容」、「构建默认大小与最大限制」。代码我放在 GitHub https://github.com/UniqueDong/algorithms.git上,自己撸一遍,再对比下是否写的正确。

    这里不仅仅作为一个 示例,我的例子还考虑了栈默认初始大小以及最大限制,当超过默认大小但是还没有达到最大限制的时候,还需要扩容操作。

    import java.util.Arrays;

    /**

    * 基于数组实现的栈

    * @param 

    */

    public class ArrayStack {

    /**

    * 默认大小

    */

    public static final int DEFAULT_SIZE = 128;

    /**

    * 默认最大限制,-1 表示无限制

    */

    private static final int DEFAULT_LIMIT = -1;

    /**

    * 初始化栈大小

    */

    private int size;

    /**

    * 栈最大限制数,-1 表示无限制

    */

    private final int limit;

    /**

    * 指向栈顶元素的下标,默认没有数据 -1

    */

    private int index;

    /**

    * 保存数据

    */

    private Object[] stack;

    /**

    * 默认构造方法,创建一个 128 大小,无限制数量的栈

    */

    public ArrayStack() {

    this(DEFAULT_SIZE, DEFAULT_LIMIT);

    }

    // 指定大小与最大限制的栈

    public ArrayStack(int size, int limit) {

    this.index = -1;

    if (limit > DEFAULT_LIMIT && size > limit) {

    this.size = limit;

    } else {

    this.size = size;

    }

    this.limit = limit;

    this.stack = new Object[size];

    }

    /**

    * push obj to stack of top

    *

    * @param obj push data

    * @return true if push success

    */

    public boolean push(T obj) {

    index++;

    // 当下标达到 size,说明需要拓容了。判断是否需要拓容

    if (index == size) {

    // 若超过限制则返回 false,否则执行拓容

    if (limit != DEFAULT_LIMIT && size >= limit) {

    index--;

    return false;

    } else {

    // 拓容

    expand();

    }

    }

    stack[index] = obj;

    return true;

    }

    /**

    * pop stack of top element

    *

    * @return top of stack element

    */

    public T pop() {

    if (index == -1) {

    return null;

    }

    T result = (T) stack[this.index];

    stack[index--] = null;

    return result;

    }

    /**

    * 清空栈数据

    */

    public void clear() {

    // 判断是否空

    if (index > -1) {

    // 只需要将 index + 1 个元素设置 null,不需要遍历 size

    for (int i = 0; i 

    stack[i] = null;

    }

    }

    index = -1;

    }

    public int size() {

    return this.index + 1;

    }

    @Override

    public String toString() {

    return "ArrayStack{" +

    "size=" + size +

    ", limit=" + limit +

    ", index=" + index +

    ", stack=" + Arrays.toString(stack) +

    '}';

    }

    }

    复制代码

    我们来分析下「栈」的空间复杂度与实践复杂度。

    在「入栈」「出栈」的操作中,存储数据都是只需要一个 最大限制 n 的数组,所以空间复杂度是 O(1)。

    存储数据为 n 大小的数组,不是说空间复杂度是 O(n),这里一定要注意。因为 这个 n 是必须的,无法省。当我们说空间复杂度的时候,指的是除原本数据存储空间外,算法还需要额外的那部分存储空间。

    不管是链式栈还是顺序栈,出栈与入栈只是设计栈顶个别数据的操作,只是需要拓容的时候会 O(n),但是均摊以后最后还是 O(1)。

    所以栈的时间与空间复杂度都是 O(1)。

    拓容实现

    当容量达到指定默认值大小的时候再入栈数据则需要拓容知道拓容到最大限制大小。

    数组拓容可以通过 System.arraycopy(stack, 0, newStack, 0, size); 当空间不足的时候申请原数组两倍大小的数组,然后把原始数据复制到新数组中。

    b085eadd0d364df013c574c15db5d3ef.png拓容

    /**

    * 扩容两倍 ,若是两倍数值超过 limit 则只能拓容到 limit

    */

    private void expand() {

    int newSize = size * 2;

    if (limit != DEFAULT_LIMIT && newSize > limit) {

    newSize = limit;

    }

    Object[] newStack = new Object[newSize];

    System.arraycopy(stack, 0, newStack, 0, size);

    this.stack = newStack;

    this.size = newSize;

    }

    复制代码

    栈的应用场景

    经典的应用场景就是 「函数调用栈」。

    操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构, 用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。

    表达式求值

    为了方便解释,我将算术表达式简化为只包含加减乘除四则运算,比如:34+13*9+44-12/3 。 对于这个四则运算,我们人脑可以很快求解出答案,但是对于计算机来说,理解这个表达式本身就是个挺难的事儿。如果换作你,让你来实现这样一个表达式求值的功能,你会怎么做呢?

    实际上编译器就是通过两个栈实现的。一个保存操作数的栈、一个则保存操作运算符的栈。

    我们从左向右遍历表达式,当遇到数字,我们就直接压入操作数栈;当遇到运算符,就与运算符栈的栈顶元素进行比较。

    如果比运算符栈顶元素的优先级高,就将当前运算符压入栈;如果比运算符栈顶元素的优先级低或者相同,从运算符栈中取栈顶运算符,从操作数栈的栈顶取 2 个操作数,然后进行计算,再把计算完的结果压入操作数栈,继续比较。如下图所示

    1f943f484e2e1007e5ff4bf73124d8ee.png

    浏览器后退前进

    我们使用两个栈,X 和 Y,我们把首次浏览的页面依次压入栈 X,当点击后退按钮时,再依次从栈 X 中出栈,并将出栈的数据依次放入栈 Y。当我们点击前进按钮时,我们依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,那就说明没有页面可以继续后退浏览了。当栈 Y 中没有数据,那就说明没有页面可以点击前进按钮浏览了。

    比如你顺序查看了 a,b,c 三个页面,我们就依次把 a,b,c 压入栈,这个时候,两个栈的数据就是这个样子:

    977a01c959ae89a685db11f03612e724.png

    点击后退,从页面 c 后退到页面 a 之后,我们就依次把 c 和 b 从栈 X 中弹出,并且依次放入到栈 Y。这个时候,两个栈的数据就是这个样子:

    63af5efdb8a96fe5557eb8caa0b997b6.png

    这时候想看 b,于是你又点击前进按钮回到 b 页面,我们就把 b 再从栈 Y 中出栈,放入栈 X 中。此时两个栈的数据是这个样子:

    5b8c52d81a341043a1573896a07a8d23.png

    这个时候,你通过页面 b 又跳转到新的页面 d 了,页面 c 就无法再通过前进、后退按钮重复查看了,所以需要清空栈 Y。此时两个栈的数据这个样子:

    f343cc7367c9e9d81db36345ceb4ea31.png

    通过来两个栈来操作,快速的实现了前进后退。

    由于篇幅原因,具体实现代码我们下文再撸,关注我一手掌握最新文章。

    推荐阅读

    1.跨越数据结构与算法

    2.时间复杂度与空间复杂度

    3.最好、最坏、平均、均摊时间复杂度

    4.线性表之数组

    5.链表导论-心法篇

    6.单向链表正确实现方式

    7.双向链表正确实现

    原创不易,觉得有用希望读者随手「在看」「收藏」「转发」三连。

    本文使用 mdnice 排版

    展开全文
  • 解释了很多前进后退函数出问题的原因。 下面是用按钮做前进后退的JS: <input type=button value=刷新 onclick="window.location.reload()"/> <input type=button value=前进 onclick="window.history....
  • 如果要你实现个前端路由,应该如何实现浏览器的前进后退 ?2. 问题首先浏览器中主要有这几个限制,让前端不能随意的操作浏览器的浏览纪录:没有提供监听前进后退的事件。不允许开发者读取浏览纪录,就是 js ...
  • 问题描述 顺序前进法和顺序后退法 要求:在sonar 和iris数据上进行验证顺序前进法和顺序后退法特征选择性能 提示:特征选择由类别可分性判据+搜索算法实现; 作业形式:上机+报告+...这是一种从底向上的方法。第一..
  • 2.从栈的操作特性来看,是一种“操作受限”的线性表,只允许在端插入和删除数据。二、为什么需要栈?1.栈是一种操作受限的数据结构,其操作特性用数组和链表均可实现。2.但,任何数据结构都是对特定应用场景的抽象,...
  • 我有一个快速的问题.我对Swing有一点经验,最简单的方法是绘制一个相当大的GUI.作为GUI的一部分,我想要前进后退按钮....在任何一种情况下,它真的很烦我.我想有可能更简单的方式,如卡片布局,但我认为这种方法应...
  • ajax是个非常好玩的小东西,不过用起来会存在一些问题。我们可以利用ajax进行无刷新改变文档内容,但是没办法去修改URL,即无法实现浏览器的前进后退、书签的收藏功能。利用location的hash部分和使用window....
  • 栈的特点是后进先出,是一种“操作受限”的线性表,只允许在一端插入和删除。当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,就应该首选“栈”这种数据结构。栈2. 如何实现栈?栈...
  • 比如本文即将要说到的功能,native由于是多页应用,新页面可以启用个的新的webview来打开,后退其实是关闭当前webview,其上个webview就自然显示出来;但是在单页的webapp应用中,所有内容其实是在个页面中...
  • 从操作特性上看,栈是一种操作受限的线性表,只允许在一端插入和删除数据。虽然使用数组和链表能够替代栈这种数据结构,但是数组与链表向外暴露了太多的api接口,操作上面虽然自由,但是使用的时候就比较不可控,...
  • vue前进加载页面后退缓存数据记录运动位置 以及 destroy替代方案
  • AJAX 网页保留浏览器前进后退等功能在一些AJAX被大量使用的页面,有时都不太敢刷新,因为刷新以后可能看到的是和原来有很大不同的页面。暂不讨论在某些页面内容大量更新的情况下是否该使用AJAX的问题,本文简单说...
  • javascript中的后退和刷新;...如果是history.go(0)那就是刷新这两个属于JS代码,相当于IE的前进后退功能。 具体的用处就要看什么时候需要这个就用上。比如用户注册时的验证是后台验证,不符合要求的时候就可以
  • 存在这一些问题:再刷新页面,页面就会变成初始的状态浏览器的前进后退功能无效对搜索引擎的爬虫抓取不友好1、早前会使用浏览器的hash锚点来解决不同的hash标记着页面不同的部分,能修正页面刷新数据不正确的...
  • 若使用vue-router,this.$router.go(-1)可以回到上页 this.$router.back() window.history.go(-1) 区别 ①与②的区别是: go(-1): 原页面表单中的内容会丢失: 1. this.$router.go(-1):后退+刷新; 2. this.$...
  • 前言:现在前后端基本都是通过ajax实现前后端接口数据的交互,但是,ajax有个小小的劣势,即:不支持浏览器“后退”和“前进“键。但是,现在我们可以通过H5的histroy属性 解决ajax在交互请求的这个小bug。事件描述...
  • 实现目标页面的跳转(前进后退,点击等)不重新请求页面页面URL与页面展现内容一致(符合人们对传统网页的认识)在不支持的浏览器下降级成传统网页的方式使用到的APIhistory.state当前URL下对应的状态信息。如果当前URL...
  • 打开新链接4方式 1. 在当前窗口打开新连接, 可后退: html: <a href="url" target="_self"> js: window.open("url", "_self"); 2. 在当前窗口打开新连接,禁止后退: js: location.replace("新url") 3. ...
  • 以前给你们分享了利用keep-alive进行缓存你想要的页面,而后到后面会出现这样的问题:我有三个组件A(组件)、B(A中的弹框)、C(组件),其实算是两个组件,个弹框,如今他们的关系是这样的:点击A(li循环列表组件)中...
  • 使用php实现禁用浏览器后退的方法:1、在头部加【】标签,并安全连接【pragma: no-cache】防止浏览器缓存页面;2、用程序控制,在【】中除去【no-store】使用php实现禁用浏览器后退的方法:最好的方案应该是:混合...
  • 后退快捷键ctrl加什么

    千次阅读 2021-07-28 01:51:15
    计算机(computer)俗称电脑,是现代一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能。是能够按照程序运行,自动、高速处理海量数据的现代化智能电子设...
  • 思路浏览器的前进后退,我们日常生活中应该接触到很多。今天就来一起思考一下,他是如何实现的。如果我是个浏览器开发者,那我要如何来实现这个功能?如果是我的话,我可能会用两个数组来存储历史记录,把访问...
  • 1 问题描述:在微信公众号开发过程中,无论是iOS或者安卓都出现后退不刷新的问题。2 造成此问题的原因:页面直接从浏览器缓存中读取。以下就解决此问题的方法并结合iOS和安卓的兼容性谈谈自己的看法和建议。3 网上...
  • 用PHP程序实现支持页面后退的两方法 在开发过程中,往往因为表单出错而返回页面的时候填写的信息都不见了,为了支持页面回跳,可以通过两方法实现。 第,使用Header方法设置消息头Cache-control header('Cache...
  • 在我们浏览不同网页的时候,我们可以通过浏览器的前进后退键来去到我们前后访问过的页面。这都有个共同点,就是 浏览器地址栏的地址改变了。浏览器自身维护了个记录用户访问页面历史的栈,栈中记录了用户访问...
  • 退出登录跳转到登录界面等,发现浏览器默认的后退按钮很是蛋疼,因为项目上是尽量前端去保存用户状态,没有后台进行session校验,故跳转的时候要注意的是后退按钮的禁用,找了几方法,感觉不错,分享出来。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,489
精华内容 14,195
关键字:

后退也是一种前进