背影遇影子 發表於 2020-11-19 16:40:00

使用 JavaScript 操作浏览器历史记录 API

<p>History 是 window 对象中的一个 JavaScript 对象,它包含了关于浏览器会话历史的详细信息。你所访问过的 URL 列表将被像堆栈一样存储起来。浏览器上的返回和前进按钮使用的就是 history 的信息。</p>
<p>History 对象包含长度属性,它包含了会话历史记录栈中的 URL 数量。例如,如果用户在浏览器中打开一个标签页,历史记录的长度将是 1(新的标签页也是一个网页)。然后用户输入一个网址 foo.com 并点击回车,现在历史记录对象的长度将是 2, 用户转到其他页面 bar.com,历史记录对象的长度将就是 3 了。</p>
<h2 id="back-和-forward-方法">Back 和 Forward 方法</h2>
<p>你可以使用 history 对象的 <code>back</code> 和 <code>forward</code> 方法来浏览网页。例如,如果你想转到上一个页面,那么可以使用:</p>
<pre><code class="language-javascript">history.back()
</code></pre>
<p>同样的,如果你想转到下一页,你可以使用:</p>
<pre><code class="language-javascript">history.forward()
</code></pre>
<h2 id="go-方法">Go 方法</h2>
<p>如果您想向前或向后移动 n 个页面,那么您可以使用 go 方法:</p>
<pre><code class="language-javascript">history.go(-2) // 倒退 2 页
history.go(2) // 前进 2 页
</code></pre>
<p>所以 <code>history.go(1)</code> 和 <code>history.forward()</code> 效果是相同的,<code>history.go(-1)</code> 和 <code>history.go(-1)</code> 效果是相同的。<code>history.go</code> 方法的默认值为 0,如果不传任何数字,则当前页面会被刷新。</p>
<pre><code class="language-javascript">window.history.go(0)
window.history.go()
</code></pre>
<h2 id="pushstate">PushState</h2>
<p>你也可以使用 <code>pushState</code> 和 <code>replaceState</code> 方法改变页面的 URL。<code>pushState</code> 会改变页面的 URL,并将改变后的 URL 添加到 <code>history</code> 对象的 URL 栈顶部。语法如下:</p>
<pre><code class="language-javascript">history.pushState(state, title, url)
</code></pre>
<p>参数 state 是状态数据,它将被存储在 history.state 变量中。参数 title 是标题文本,不过它对大多数浏览器都没有效果,所以一般传空字符串("")或传 null 就可以了。</p>
<p>让我们在控制台中尝试一下,在执行之前,比如打开 baidu.com,然后在控制台输入:</p>
<pre><code class="language-javascript">history.pushState('123', '', 'new-url')
</code></pre>
<p>执行上面的代码后,它会将页面地址栏中的 URL 改为 baidu.com/new-url,同时将 URL 添加到 history 对象中。此时检查 <code>history.length</code> 会增加 1。</p>
<p>除此之外,我们还可以为每个 URL 存储状态(当前页面的数据)。在上面的例子中,你会把 "123" 存储在 <code>history.state</code> 变量中,当你返回到这个页面时,你就可以 <code>history.state</code> 再次拿到到这些数据。例如:</p>
<pre><code class="language-javascript">history.pushState('temp data 1', 'title', 'new-url-1')
history.state //"temp data 1"
history.pushState('temp data 2', 'title', 'new-url-2')
history.state //"temp data 2"
history.back()
history.state // "temp data 1"
</code></pre>
<p>每当通过 pushState 返回到之前被添加到历史记录的页面时,浏览器就会触发一个名为 popstate 的事件,并将 state 数据作为参数。比如在浏览器打开一个新标签页,进入某个网页(比如 baidu.com),先监听 popstate 事件:</p>
<pre><code class="language-javascript">window.addEventListener('popstate', (e) =&gt; console.log(e))
</code></pre>
<p>然后调用 pushState:</p>
<pre><code class="language-javascript">history.pushState({ name: 'test1' }, 'title', 'test1')
</code></pre>
<p>然后按下返回按钮,popstate 事件就会被触发,你可以在监听事件中查看打印出来的数据。在打印的数据中,可以找到 history.state 的值。</p>
<p>注册 pushState 中的 url 可以是完整的 url,但必须和当前页面是相同的域名,否则会抛出跨域异常。</p>
<p>浏览器还有一个 <code>replaceState</code> API,和 <code>pushState</code> 的区别是,它只改变了 URL,不会将 URL 添加到历史记录,这里就不再累述了。</p>
<h2 id="实例演示">实例演示</h2>
<p>现在我们做一个小的网页应用,这个应用将实现如下功能:</p>
<ol>
<li>显示用户列表</li>
<li>可以通过下拉框筛选“先生”和“女士”</li>
<li>当下列列表发生变化时,URL 也会相应的变化</li>
</ol>
<p>我们先不关心 history API,先实现功能。下面是 html 关键代码:</p>
<pre><code class="language-html">&lt;select id="selectbox"&gt;
&lt;option value="both"&gt;全部&lt;/option&gt;
&lt;option value="male"&gt;先生&lt;/option&gt;
&lt;option value="femalt"&gt;女士&lt;/option&gt;
&lt;/select&gt;
&lt;ul id="userslist"&gt;
&lt;li gender="male"&gt;张先生&lt;/li&gt;
&lt;li gender="female"&gt;李女士&lt;/li&gt;
&lt;li gender="female"&gt;王女士&lt;/li&gt;
&lt;/ul&gt;
</code></pre>
<p>下面是 javascript 关键代码:</p>
<pre><code class="language-javascript">let selectBox = document.getElementById('selectBox')
let usersList = document.getElementById('usersList')

selectBox.addEventListener('change', onSelectBoxChange)

function onSelectBoxChange(ev) {
let val = this.value
filterList(val)
}

function filterList(val) {
let users = usersList.children
for (let i = 0; i &lt; users.length; i++) {
    let user = users
    let gender = user.getAttribute('gender')
    if (gender === val || val === 'both') {
      user.style.display = ''
    } else {
      user.style.display = 'none'
    }
}
}
</code></pre>
<p>实现后的效果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/2037256/202011/2037256-20201119163630091-1215473347.gif" alt="" loading="lazy"></p>
<p>当修改下拉列表时,为了使浏览器地址也发生变化,需要使用 <code>pushSate</code> 方法:</p>
<pre><code class="language-javascript">function onSelectBoxChange(ev) {
let val = this.value
filterList(val)
history.pushState({ gender: val }, null, val)
}
</code></pre>
<p>当我们在下拉框选择“先生”时,浏览器的地址会变成:localhost:5000/male。效果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/2037256/202011/2037256-20201119163642027-1190679753.gif" alt="" loading="lazy"></p>
<p>此时会有个问题,当我们点击前进/后退时,浏览器地址变了,但对应的数据却不对。因此,当进行前进/后退时,我们需要监听 popstate 重新过滤数据:</p>
<pre><code class="language-javascript">window.addEventListener('popstate', onPopState)
function onPopState(ev) {
let state = ev.state
filterList(state.gender)
}
</code></pre>
<p>我们还需要处理页面刷新的问题。当刷新页面时,历史记录不会改变,<code>history.state</code> 的状态值也保持不变。所以我们可以从 <code>history.state</code> 中取出当前的状态数据,利用 <code>state.gender</code> 的值就可以在 <code>load</code> 事件中来过虑出当前 URL 对应的用户列表:</p>
<pre><code class="language-javascript">window.addEventListener('load', function () {
let gender = history.state ? history.state.gender : 'both'
filterList(gender)
})
</code></pre>
<p>这是个简单的示例,你也可以继续进一步优化。今天的分享就到这里,有问题请在下面留言哦~~</p><br><br>
来源:https://www.cnblogs.com/fehoney/p/14006413.html
頁: [1]
查看完整版本: 使用 JavaScript 操作浏览器历史记录 API