顶部导航栏 vue3.0 代码实现

作品示例:

TagsView.vue的代码实现

<template><div class="content"><div class="content-left"><el-button icon="el-icon-arrow-left" type="primary" @click="handleNavClick('RIGHT')"></el-button><div ref="navTagsRef" class="tags-view-container"><template v-for="tag in Array.from(visitedViews)"  :key="tag.path"><el-dropdown trigger="contextmenu"><el-tagref="tag":class="tag.path === $route.path ? 'active-el-tag' : ''"closable@click="clickTag(tag.path, tag.query)"@close.prevent.stop="closeSelectedTag(tag)">{{ tag.meta.title }}</el-tag><template #dropdown><el-dropdown-menu><el-dropdown-item @click="closeSelectedTag(tag)">关闭</el-dropdown-item><el-dropdown-item @click="closeOthersTags(tag)">关闭其他</el-dropdown-item><el-dropdown-item @click="closeAllTags()">关闭所有</el-dropdown-item></el-dropdown-menu></template></el-dropdown></template></div></div><el-button icon="el-icon-arrow-right" type="primary" @click="handleNavClick('LEFT')"></el-button></div>
</template><script>
import {ft} from '@pinkbin/utils'
import {reactive, ref, toRefs} from 'vue'
import {useRouter} from 'vue-router'export default {name: 'tags-view',data () {return {visible: false,top: 0,left: 0,selectedTag: {}}},computed: {visitedViews () {return this.$store.state.tagsView.visitedViews}},watch: {$route () {this.addViewTags()},visible (value) {if (value) {document.body.addEventListener('click', this.closeMenu)} else {document.body.removeEventListener('click', this.closeMenu)}}},mounted () {this.addViewHome()},setup () {const {push} = useRouter()const state = reactive({childMode: {},dialogGetParentVisible: false,contentTree: []})const navTagsRef = ref()// 点击标签路由跳转const clickTag = (path, query) => {push(path, query)}// 左右移动const handleNavClick = (d) => {const dom = navTagsRef.valueconsole.log(dom)if (!dom) returnlet origin = dom.scrollLeftconst {scrollWidth, offsetWidth} = domconst diff = scrollWidth - offsetWidth // 滚动到最右侧的距离const distance = d === 'RIGHT' ? diff - origin : -originlet ani = 0let preTime = performance.now();(function frame (currTime = performance.now()) {// 超出范围之后就停止动画if ((d === 'RIGHT' && origin >= diff) || (d === 'LEFT' && origin <= 0)) return cancelAnimationFrame(ani)const step = ft(currTime - preTime, distance)dom.scrollLeft = origin += steppreTime = currTimeani = requestAnimationFrame(frame)})()}return {clickTag,navTagsRef,handleNavClick,...toRefs(state)}},methods: {generateRoute () {if (this.$route.name) {return this.$route}return false},isActive (route) {return route.path === this.$route.path},addViewTags () {const route = this.generateRoute()if (!route) {return false}let item = {meta: route.meta,path: route.path,query: route.query}console.log(route)this.$store.dispatch('addVisitedViews', item)},addViewHome () {let item = {meta: {title: '首页'},path: '/home',query: ''}this.$store.dispatch('addVisitedViews', item)},closeSelectedTag (view) {if (view.path === '/home') {return}this.$store.dispatch('delVisitedViews', view).then(views => {if (this.isActive(view)) {const latestView = views.slice(-1)[0]if (latestView) {this.$router.push(latestView)} else {this.$router.push('/')}}})},closeOthersTags (view) {this.$router.push(view)this.$store.dispatch('delOthersViews', view)// .then()},closeAllTags () {this.$store.dispatch('delAllViews')this.$router.push('/')},openMenu (tag, e) {this.visible = truethis.selectedTag = tag// const offsetLeft = this.$el.getBoundingClientRect().leftthis.left = e.clientXthis.top = e.clientY},closeMenu () {this.visible = false}}
}
</script><style lang="scss" scoped>
.content {display: flex;justify-content: space-between;overflow: hidden;border-top: 1px solid #366AE4;border-bottom: 1px solid #366AE4;.el-button--primary {background-color: #FFFFFF;min-height: 10px;height: 32px;min-width: 10px;width: 30px;border-radius: 0;border-color: #366AE4;color: #333333;text-align: center;line-height: 10px;border-top: none;border-bottom: none;}.el-button {padding: 0;}.content-left {display: flex;width: 98%;.tags-view-container {height: 100%;display: flex;justify-content: start;align-items: center;overflow: hidden;::v-deep .el-tag {border-radius: 0;background-color: #FFFFFF;border-color: #366AE4;border-left: none;border-top: none;border-bottom: none;}.active-el-tag {background-color: #4777E7;font-size: 16px;font-weight: 400;color: #FFFFFF;.el-tag .el-tag__close {color: #FFFFFF;}}}}
}
</style>

vuex的源代码tagsView.js

const tagsView = {state: {visitedViews: [],cachedViews: []},mutations: {ADD_VISITED_VIEWS: (state, view) => {if (state.visitedViews.some(v => v.path === view.path)) returnif (view.path === '/userAuth/login') returnstate.visitedViews.push(Object.assign({}, view, {title: view.meta.title || 'no-name'}))if (!view.meta.noCache) {state.cachedViews.push(view.name)}},DEL_VISITED_VIEWS: (state, view) => {for (const [i, v] of state.visitedViews.entries()) {if (v.path === view.path) {state.visitedViews.splice(i, 1)break}}for (const i of state.cachedViews) {if (i === view.name) {const index = state.cachedViews.indexOf(i)state.cachedViews.splice(index, 1)break}}},DEL_OTHERS_VIEWS: (state, view) => {for (const [i, v] of state.visitedViews.entries()) {if (v.path === view.path) {state.visitedViews = state.visitedViews.slice(i, i + 1)break}if (v.path === '/home') {state.visitedViews = state.visitedViews.slice(i, i + 1)break}}for (const i of state.cachedViews) {if (i === view.name) {const index = state.cachedViews.indexOf(i)state.cachedViews = state.cachedViews.slice(index, i + 1)break}}},DEL_ALL_VIEWS: (state) => {let item = {meta: {title: '首页'},path: '/home',query: ''}state.visitedViews = []state.visitedViews.push(item)state.cachedViews = []}},actions: {addVisitedViews({commit}, view) {commit('ADD_VISITED_VIEWS', view)},delVisitedViews({commit,state}, view) {return new Promise((resolve) => {commit('DEL_VISITED_VIEWS', view)resolve([...state.visitedViews])})},delOthersViews({commit,state}, view) {return new Promise((resolve) => {commit('DEL_OTHERS_VIEWS', view)resolve([...state.visitedViews])})},delAllViews({commit,state}) {return new Promise((resolve) => {commit('DEL_ALL_VIEWS')resolve([...state.visitedViews])})}}
}export default tagsView

nav-tage、vue3.0顶部历史浏览记录代码实现 vuex + el + vue3.0相关推荐

  1. 使用redis存储历史浏览记录

    使用redis存储历史浏览记录 核心是分析流程 1.什么时候需要添加历史浏览记录? 访问具体商品详情页面时 2.什么时候需要获取历史浏览记录? 根据具体情况而定 3.存储在哪? redis数据库,如果 ...

  2. Django中--使用redis存储历史浏览记录

    class UserInfoView(LoginRequiredMixin, View):'''用户中心-信息页'''def get(self, request):'''显示'''# Django会给 ...

  3. Redis添加历史浏览记录

    参考资料 http://redisdoc.com/index.html http://redis-py.readthedocs.io/en/latest/#indices-and-tables 1.什 ...

  4. position:搜索框显示历史浏览记录

    absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位. 元素的位置通过 "left", "top", "righ ...

  5. easyui onclickrow 中获取列名_获取Chrome浏览器历史浏览记录实例

    1.获取谷歌浏览器浏览历史保存位置,并拷贝一份到操作目录下2.找到浏览记录文件 "History"3.将"History"文件导出到其他目录下4.查看数据库ta ...

  6. js操作Cookie,实现历史浏览记录

    /*** history_teacher.jsp中的js,最近浏览名师* @version: 1.0* @author: mingming*/ $(function(){getHistory(); } ...

  7. 【01】网页中清除历史浏览记录能不能彻底删除浏览记录?

    不能-- 即便你把记录全删了,也可用数据恢复工具给你找回来: 即便你用专业工具覆盖N遍,确保数据无法恢复,网站那头还记着哪个ip什么时候访问过哪些内容呢--然后跑ISP(联通或电信)一查,xx时间xx ...

  8. Google Chrome 搜索特定日期的历史浏览记录

    https://myactivity.google.com 上这个网址filter and search

  9. 怎么查看html页面,网页浏览记录如何查看_怎样查历史网页浏览记录-win7之家

    大家都喜欢通过浏览器来浏览一些网页,当我们浏览或者查阅网页的HIA,都会留下历史记录,这样就可以方便我们通过查看自己的网页浏览历史记录来查找了,那么网页浏览记录如何查看呢?针对这个问题,本文给大家讲解 ...

  10. php写浏览记录,php如何浏览历史记录

    这篇文章主要介绍了php浏览历史记录的方法,涉及php操作cookie的技巧,非常具有实用价值,需要的朋友可以参考下 本文实例讲述了php浏览历史记录的方法. 具体实现方法如下:/** * 商品历史浏 ...

最新文章

  1. HTML5代码基础结构
  2. java set删除第一个元素_Java面试题10(如何取到set集合的第一个元素)
  3. c语言printf族函数,C语言中的printf族函数深入详解
  4. echarts设置网格线颜色
  5. 转:技术宅逆天了!如何从按键音中听出周鸿祎的手机号码
  6. 在metasploitable里面搭建ZVulDrill
  7. 开培训会没人来,是正常的
  8. ARM开发7.3.4 基础实训( 4 ) 矩阵式键盘的输入系统设计--LPC21XX
  9. PHOTOSHOP教程
  10. [教程]Web自动化测试怎么做?Web网页测试全流程解析
  11. 机械电子计算机哪个更适合创业,二本 电气工程及其自动化,和机械电子工程 哪个专业技术性很强,更好就业,更适合考研。...
  12. java游戏貂蝉_血战三国之吕布貂蝉
  13. 树莓派做网络代理_【树莓派】设置代理服务器联网
  14. iOS实现APP支持SpotLight搜索
  15. elementUI表格合并单元格详解
  16. DNX 版本升级命令
  17. 用20门编程语言说生日快乐/我爱你
  18. 02333软件工程——结构化方法
  19. HTTP与HTTPS,HTTPS更加安全。
  20. oracle数据库主机CPU使用率高问题的分析及SQL优化

热门文章

  1. android流光动画和流光字体
  2. [VOA美国人物] Jackie Robinson: The First Black Player in Modern Major League
  3. 我叔叔愿意从事计算机工作英语翻译,我的叔叔作文
  4. 把服务器当网盘玩 教你从云服务器下载自己的文件
  5. win8.1配置java环境
  6. 做服务器销售两个月还没开单,1月15日的销售欠款,2月20日做的收款单,为什么没有...
  7. vuecli2+axios 设置多个域名代理
  8. 遇到【java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter】的解决方案
  9. access行列转换。
  10. 硬盘分区形式之MBR、GPT