国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn)

這篇具有很好參考價(jià)值的文章主要介紹了Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

說明

這里記錄下自己在Vue3+vite的項(xiàng)目使用less來寫樣式以及使用vite-plugin-vue-setup-extend直接定義組件name,不使用ts語法,方便以后直接使用。這里承接自己的博客Vue3+vite搭建基礎(chǔ)架構(gòu)(10)— 使用less和vite-plugin-vue-setup-extend這篇博客,在該博客項(xiàng)目的基礎(chǔ)上增加菜單欄功能和Tab頁功能實(shí)現(xiàn)。

刪除項(xiàng)目中不需要的文件

刪除掉src文件夾下的style.css和compoments文件夾下的HelloWorld.vue以及assets文件夾下的vue.svg圖片,這三個(gè)都是項(xiàng)目創(chuàng)建完成后自帶的,因?yàn)橛貌坏剿詣h除掉。
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
刪除views下面home文件夾下的index.vue代碼,因?yàn)檫@個(gè)里面代碼是以前用來測(cè)試依賴的代碼,所以把代碼清空,保留為一個(gè)空文件。
代碼如下:

<!--home首頁代碼-->
<template>
  <div>我是首頁</div>
</template>

<script setup name="home">

</script>

<style lang="less" scoped>

</style>

在src下面新建styles文件夾用來存放全局樣式。common.less用來存放html標(biāo)簽樣式。element-plus.less用來存放ElementPlus組件里面的標(biāo)簽樣式。然后在main.js里面引入2個(gè)樣式文件,讓它們?nèi)稚А?br>Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5

common.less里面代碼如下:

//body全局樣式設(shè)計(jì)
body{
  font-size: 14px;//字體大小
  margin: 0px;
  padding: 0px;
}

//a標(biāo)簽全局樣式
a {
  color: #1B68B6;//字體顏色
  text-decoration: none;//去掉下劃線
  cursor: pointer;//鼠標(biāo)放上去手型
  //鼠標(biāo)放上去顏色
  /*&:hover {
    color: #1B68B6;
  }
  //鼠標(biāo)點(diǎn)擊時(shí)顏色
  &:active{
    color: #1B68B6;
  }
  //鼠標(biāo)點(diǎn)擊后獲取焦點(diǎn)樣式
  &:focus {
    color: #1B68B6;
  }*/
}

element-plus.less目前代碼為空。

userStore全局屬性代碼

在store文件夾下的modules文件夾下的userStore.js文件修改代碼為如下:

//使用pinia來管理全局狀態(tài)
import { defineStore } from "pinia"

/*defineStore 是需要傳參數(shù)的,其中第一個(gè)參數(shù)是id,就是一個(gè)唯一的值,
簡(jiǎn)單點(diǎn)說就可以理解成是一個(gè)命名空間.
第二個(gè)參數(shù)就是一個(gè)對(duì)象,里面有三個(gè)模塊需要處理,第一個(gè)是 state,
第二個(gè)是 getters,
第三個(gè)是 actions。
*/
//聲明了一個(gè)useUserStore方法
const useUserStore = defineStore('user', {
  //準(zhǔn)備state——用于存儲(chǔ)數(shù)據(jù)
  state: () => {
    return {
      //當(dāng)前激活菜單的index
      activeMenu: '',
      //綁定值,選中選項(xiàng)卡的name
      editableTabsValue: '',
      //tab標(biāo)簽選項(xiàng)卡內(nèi)容
      editableTabs: [],
      //tab頁路由地址及參數(shù)
      tabRouterList: []
    }
  },
  //使用persist插件對(duì)state里面屬性進(jìn)行緩存
  persist: {
    enabled: true,//開啟緩存,默認(rèn)緩存所有state里面的屬性,默認(rèn)key為defineStore里面的id值,這里id值為user,所以默認(rèn)key為user
    //自定義持久化參數(shù),指定以下state里面的屬性進(jìn)行緩存,未指定的不進(jìn)行緩存
    strategies: [
      {
        // 自定義key
        key: 'activeMenu',
        // 自定義存儲(chǔ)方式,默認(rèn)sessionStorage
        storage: sessionStorage,
        // 指定要持久化的數(shù)據(jù)
        paths: ['activeMenu']
      },
      {
        key: 'editableTabsValue',
        storage: sessionStorage,
        paths: ['editableTabsValue']
      },
      {
        key: 'editableTabs',
        storage: sessionStorage,
        paths: ['editableTabs']
      },
      {
        key: 'tabRouterList',
        storage: sessionStorage,
        paths: ['tabRouterList']
      }
    ]
  },
  getters: {

  },
  //準(zhǔn)備actions——用于響應(yīng)組件中的動(dòng)作和用于操作數(shù)據(jù)(state),pinia中只有state、getter、action,拋棄了Vuex中的Mutation
  actions: {
    /**
     * 修改state中數(shù)據(jù)的方法
     * @param name 需要修改的屬性名
     * @param value 修改值
     */
    updateState([name, value]) {
      this[name] = value
    },
    //動(dòng)態(tài)添加tab標(biāo)簽,item為當(dāng)前點(diǎn)擊的菜單項(xiàng)
    addTab(item) {
      const newTab = {
        title: item.meta.title,
        name: item.url,
        iconClass: item.meta.icon,
      }
      // 判斷當(dāng)前editableTabs中是否存在該tab標(biāo)簽
      if (this.editableTabs.findIndex(item => item.title === newTab.title) === -1) {
        this.editableTabs.push(newTab);
        this.editableTabsValue = newTab.name;
        this.activeMenu = newTab.name;
      }
    },
    //移除tab標(biāo)簽
    removeTab(targetName) {
      let tabs = this.editableTabs
      let activeName = this.editableTabsValue
      if (activeName === targetName) {
        tabs.forEach((tab, index) => {
          if (tab.name === targetName) {
            let nextTab = tabs[index + 1] || tabs[index - 1]
            if (nextTab) {
              activeName = nextTab.name
            }
          }
        })
      }
      this.activeMenu = activeName
      this.editableTabsValue = activeName
      this.editableTabs = tabs.filter(tab => tab.name !== targetName)
      this.tabRouterList = this.tabRouterList.filter(item => item.path !== targetName)
    }
  }
})

export default useUserStore

菜單欄代碼

views文件下layout文件夾下的layout.vue布局代碼如下:

<template>
  <div>
    <el-container>
      <!--側(cè)邊欄,height: 100vh;設(shè)置高度為視口高度-->
      <el-aside style="width: 200px;height: 100vh;">
        <SliderBar></SliderBar>
      </el-aside>
      <el-container>
        <!--頭部-->
        <el-header>
          <Navbar></Navbar>
        </el-header>
        <!--主體內(nèi)容-->
        <el-main>
          <!--主體內(nèi)容-->
          <AppMain>
          </AppMain>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
  import { Navbar, SliderBar, AppMain } from './components/index.js'

  export default {
    name: "layout",
    components: {
      Navbar,
      SliderBar,
      AppMain
    }
  }
</script>

<style scoped>

</style>

views文件下layout文件夾下的components文件夾下sliderBar文件夾下的sliderBar.vue代碼如下:

<!--通用布局側(cè)邊欄內(nèi)容-->
<template>
  <el-row>
    <el-col>
      <div class="header">
        <!--系統(tǒng)logo,隨便找一個(gè)圖片示例用-->
        <SvgIcon iconClass="systemManagement" />
        <span class="icon-text">后臺(tái)管理系統(tǒng)</span>
      </div>
      <!--router表示為啟動(dòng)路由模式,路由模式下index為你的頁面路由路徑-->
      <!--通過設(shè)置default-active屬性點(diǎn)擊tab頁時(shí),自動(dòng)選中左邊菜單欄選項(xiàng)-->
      <div>
        <el-menu
            active-text-color="#1B68B6"
            background-color="#FFFFFF"
            :default-active="store.activeMenu"
            text-color="#333333"
            @select="handleSelect"
            :router="true"
            class="menu-items"
        >
          <!--引用菜單樹組件將路由的菜單欄循環(huán)顯示出來-->
          <MenuTree :menuList="menuTreeList"/>
        </el-menu>
      </div>
    </el-col>
  </el-row>
</template>

<script setup name="SliderBar">
  //引入菜單列表組件
  import MenuTree from "./menuTree.vue"
  //引入全局狀態(tài)里面的關(guān)于菜單欄列表數(shù)據(jù)和相關(guān)方法
  import useUserStore from "@/store/modules/userStore"
  //使用useUserStore里面的屬性
  const store = useUserStore()

  //菜單激活回調(diào)函數(shù),當(dāng)tab頁已經(jīng)打開的情況下,再次點(diǎn)擊菜單項(xiàng),對(duì)應(yīng)的tab頁也跟著切換
  function handleSelect(key) {
    store.updateState(["editableTabsValue", key])
    store.updateState(["activeMenu", key])
  }

  //菜單樹列表,這里模擬后端接口請(qǐng)求返回的數(shù)據(jù),示例數(shù)據(jù)如下:
  const menuTreeList = [
    {
      id: 1,
      url: "/test-management1",//該url要與路由文件里面的path值要一致
      level: 1,//菜單等級(jí)
      meta: { title: "測(cè)試管理1", icon: "systemManagement" },
      children: [] //子菜單
    },
    {
      id: 2,
      url: "/system-management",
      level: 1,
      meta: { title: "系統(tǒng)管理", icon: "systemManagement" },
      children: [
        {
          id: 3,
          url: "/user-management",
          level: 2,
          meta: { title: "用戶管理", icon: "userManagement" },
          children: []
        },
        {
          id: 4,
          url: "/role-management",
          level: 2,
          meta: { title: "角色管理", icon: "roleManagement" },
          children: []
        },
        {
          id: 5,
          url: "/permission-management",
          level: 2,
          meta: { title: "權(quán)限管理", icon: "permissionManagement" },
          children: []
        },
        {
          id: 6,
          url: "/password-management",
          level: 2,
          meta: { title: "密碼管理", icon: "systemManagement" },
          children: []
        },
      ],
    },
    {
      id: 7,
      url: "/test-management2",
      level: 1,
      meta: { title: "測(cè)試管理2", icon: "systemManagement" },
      children: []
    },
    {
      id: 8,
      url: "/test-management3",
      level: 1,
      meta: { title: "測(cè)試管理3", icon: "systemManagement" },
      children: [
        {
          id: 9,
          url: "/test-management4",
          level: 2,
          meta: { title: "測(cè)試管理4", icon: "systemManagement" },
          children: [
            {
              id: 10,
              url: "/test-management5",
              level: 3,
              meta: { title: "測(cè)試管理5", icon: "systemManagement" },
              children: []
            }
          ]
        }
      ]
    }
  ]
</script>

<style lang="less" scoped>
.header {
  height: 64px;
  display: flex;
  align-items: center; //垂直居中
  justify-content: left; //水平居左
  	//logo樣式
    .svg-icon {
      width: 64px;
      height: 32px;
    }
	.icon-text {
	  font-size: 16px;
	  color: #1b68b6;
	  margin-left: -5px;
	}
}

//普通菜單懸浮樣式
:deep(.el-menu-item:hover) {
  background-color: #E8EFF7;//背景顏色
  color: #1B68B6;//字體顏色
}

//子菜單懸浮樣式,子菜單的圖標(biāo)顏色需要修改svg圖片里面的fill值,由fill="#333333"改為fill="currentColor"后,圖標(biāo)懸浮樣式顏色才會(huì)一起變化
:deep(.el-sub-menu__title:hover) {
  background-color: #E8EFF7;//背景顏色
  color: #1B68B6;//字體顏色
}

//菜單被選中的樣式
:deep(.el-menu .el-menu-item.is-active) {
  background-color: #E8EFF7; //背景顏色
  color: #1B68B6; //字體顏色
  border-right: 3px solid #1B68B6;//右邊框顏色
}

//子菜單被選中的樣式
:deep(.el-sub-menu.is-active .el-sub-menu__title){
  color: #1B68B6; //字體顏色
}

//菜單欄樣式
.menu-items {
  height: 100%; //設(shè)置高度為父容器高度
  border-right: none;//去掉菜單欄右邊框
}
</style>

views文件下layout文件夾下的components文件夾下sliderBar文件夾下的menuTree.vue代碼如下:

<!--菜單樹列表-->
<template>
  <!--將菜單列表循環(huán)出來-->
  <template v-for="item in menuList">
    <!--判斷菜單里面是否有子菜單-->
    <el-sub-menu
        :key="item.id"
        :index="item.url"
        v-if="item.children.length"
    >
      <template #title>
        <el-icon><SvgIcon :iconClass="item.meta.icon"></SvgIcon></el-icon>
        <span>{{ item.meta.title }}</span>
      </template>
      <!--調(diào)用自身循環(huán)顯示子菜單-->
      <MenuTree :menuList="item.children" />
    </el-sub-menu>
    <!--菜單節(jié)點(diǎn)-->
    <el-menu-item
        v-else
        :key="item.id"
        :index="item.url"
        @click="store.addTab(item)"
    >
      <el-icon><SvgIcon :iconClass="item.meta.icon"></SvgIcon></el-icon>
      <span>{{ item.meta.title }}</span>
    </el-menu-item>
  </template>
</template>

<script setup name="MenuTree">
  //引入全局狀態(tài)里面的關(guān)于菜單欄列表數(shù)據(jù)和相關(guān)方法
  import useUserStore from "@/store/modules/userStore"
  const store = useUserStore()
  //定義屬性給組件接收
  const props = defineProps({
    //菜單欄屬性
    menuList: {
      type: Array,//類型為數(shù)組
      //默認(rèn)值為空數(shù)組
      default() {
        return []
      }
    }
  })
</script>

<style scoped>

</style>

在views文件夾下新建菜單樹列表里面對(duì)應(yīng)的頁面文件,每個(gè)頁面文件加上如下一句代碼,用來表示不同頁面內(nèi)容。
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
src文件下router文件夾下的index.js代碼如下:

//引入router路由做頁面請(qǐng)求
import { createRouter,createWebHashHistory } from 'vue-router'
/* Layout通用組件 */
import Layout from '../views/layout/layout'

const routes = [
  {path: '/404', component: () => import('@/views/404')},
  //必須要把組件放在Layout的children里面,才能在側(cè)邊欄的右側(cè)顯示頁面內(nèi)容,否則不加載通用架構(gòu)直接在當(dāng)前空白頁面渲染內(nèi)容,如:404頁面
  {
    path: '',
    component: Layout,
    redirect: '/home',
    children: [
      {
        path: 'home',
        name: 'home',
        component: () => import('@/views/home/index'),
        meta: {title: '首頁', icon: 'home'}
      },
      {
        path: 'test-management1',
        name: 'test-management1',
        component: () => import('@/views/test-management1/index'),
        meta: {title: '測(cè)試管理1', icon: 'systemManagement'}
      },
      {
        path: 'user-management',
        name: 'user-management',
        component: () => import('@/views/system-management/user-management'),
        meta: {title: '用戶管理', icon: 'userManagement'}
      },
      {
        path: 'role-management',
        name: 'role-management',
        component: () => import('@/views/system-management/role-management'),
        meta: {title: '角色管理', icon: 'roleManagement'}
      },
      {
        path: 'permission-management',
        name: 'permission-management',
        component: () => import('@/views/system-management/permission-management'),
        meta: {title: '權(quán)限管理', icon: 'permissionManagement'}
      },
      {
        path: 'password-management',
        name: 'password-management',
        component: () => import('@/views/system-management/password-management'),
        meta: {title: '密碼管理', icon: 'systemManagement'}
      },
      {
        path: 'test-management2',
        name: 'test-management2',
        component: () => import('@/views/test-management2/index'),
        meta: {title: '測(cè)試管理2', icon: 'systemManagement'}
      },
      {
        path: 'test-management5',
        name: 'test-management5',
        component: () => import('@/views/test-management5/index'),
        meta: {title: '測(cè)試管理5', icon: 'systemManagement'}
      }
    ]
  }
]

// 3. 創(chuàng)建路由實(shí)例并傳遞 `routes` 配置
const router = createRouter({
  // 4. 內(nèi)部提供了 history 模式的實(shí)現(xiàn)。為了簡(jiǎn)單起見,我們?cè)谶@里使用 hash 模式。
  history: createWebHashHistory(),
  routes, // `routes: routes` 的縮寫
})

//路由前置守衛(wèi)
router.beforeEach((to, from, next) => {
  //路由發(fā)生變化修改頁面title
  if (to.meta.title) {
    document.title = to.meta.title
  }
  next()
})

//導(dǎo)出路由
export default router

啟動(dòng)項(xiàng)目后,瀏覽器結(jié)果如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5

點(diǎn)擊不同的菜單欄選項(xiàng),頁面內(nèi)容也會(huì)相應(yīng)的變化,這種算是單頁面,activeMenu也會(huì)相應(yīng)的變化,之所以要把這個(gè)寫到session storage里面,是為了防止頁面刷新時(shí),點(diǎn)擊的高亮菜單選項(xiàng)消失問題。
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5

Tab頁代碼

views文件下layout文件夾下的components文件夾下的navbar.vue代碼如下:

<!--通用布局頭部?jī)?nèi)容-->
<template>
  <el-row>
    <el-col :span="20">
      <el-tabs
          v-model="store.editableTabsValue"
          type="border-card"
          closable
          @tab-remove="handleTabRemove"
          @tab-click="handleTabClick"
          v-if="store.editableTabs.length !== 0">
        <el-tab-pane v-for="item in store.editableTabs" :key="item.name" :name="item.name" :label="item.title">
          <!-- 右鍵菜單開始:自定義標(biāo)簽頁顯示名稱,保證每個(gè)標(biāo)簽頁都能實(shí)現(xiàn)右鍵菜單 -->
          <template #label>
            <el-dropdown
                trigger="contextmenu"
                :id="item.name"
                @visible-change="handleChange($event, item.name)"
                ref="dropdownRef">
              <span style="font-size: 16px;color: #909399;"
                    :class="store.editableTabsValue === item.name ? 'label' : ''">
                <SvgIcon :iconClass="item.iconClass"></SvgIcon>{{ item.title }}
              </span>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item @click="closeCurrent(item.name)">
                    <el-icon>
                      <Close />
                    </el-icon>關(guān)閉當(dāng)前標(biāo)簽頁
                  </el-dropdown-item>
                  <el-dropdown-item @click="closeLeft(item.name)" v-if="show(item.name, 'left')">
                    <el-icon>
                      <DArrowLeft />
                    </el-icon>關(guān)閉左側(cè)標(biāo)簽頁
                  </el-dropdown-item>
                  <el-dropdown-item @click="closeRight(item.name)" v-if="show(item.name, 'right')">
                    <el-icon>
                      <DArrowRight />
                    </el-icon>關(guān)閉右側(cè)標(biāo)簽頁
                  </el-dropdown-item>
                  <el-dropdown-item @click="closeOther(item.name)" v-if="store.editableTabs.length > 1">
                    <el-icon>
                      <Operation />
                    </el-icon>關(guān)閉其他標(biāo)簽頁
                  </el-dropdown-item>
                  <el-dropdown-item @click="closeAll()">
                    <el-icon>
                      <Minus />
                    </el-icon>關(guān)閉全部標(biāo)簽頁
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </template>
          <!-- 右鍵菜單結(jié)束 -->
        </el-tab-pane>
      </el-tabs>
    </el-col>
    <el-col :span="4">
      <div class="header">
        <!-- 用戶信息 -->
        <!--trigger="click"通過點(diǎn)擊下標(biāo)觸發(fā)-->
        <div style="cursor: pointer;">
          <el-dropdown trigger="click">
          <span>
            {{ username }}
            <SvgIcon iconClass="arrowDown" />
          </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="logout">
                  退出登錄
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </div>
    </el-col>
  </el-row>
</template>

<script setup name="navbar">
  //引入全局狀態(tài)里面的關(guān)于菜單欄列表數(shù)據(jù)和相關(guān)方法
  import useUserStore from '@/store/modules/userStore'
  import { useRouter, useRoute } from "vue-router"
  import { onMounted, ref, computed } from 'vue'
  import {
    Close,
    DArrowLeft,
    DArrowRight,
    Operation,
    Minus
  } from '@element-plus/icons-vue'

  //接手全局狀態(tài)里面的屬性和方法
  const store = useUserStore();
  //使用路由相當(dāng)于$router,系統(tǒng)路由方法
  const router = useRouter()
  //使用路由相當(dāng)于$route,點(diǎn)擊菜單欄時(shí)當(dāng)前點(diǎn)擊的路由頁面里面的屬性值
  const route = useRoute()
  //用戶名
  const username = '超級(jí)管理員'

  //觸發(fā)右鍵菜單標(biāo)簽頁為第一個(gè)時(shí),不展示【關(guān)閉左側(cè)標(biāo)簽頁】
  //觸發(fā)右鍵菜單標(biāo)簽頁為最后一個(gè)時(shí),不展示【關(guān)閉右側(cè)標(biāo)簽頁】
  const show = (name, type) => {
    const index = store.editableTabs.findIndex((item) => name === item.name)
    return type === 'left' ? index !== 0 : index !== store.editableTabs.length - 1
  }

  //右鍵菜單ref
  const dropdownRef = ref()

  //在觸發(fā)右鍵菜單后,關(guān)閉其他tab頁上的右鍵菜單
  const handleChange = (visible, name) => {
    if (!visible) return
    dropdownRef.value.forEach((item) => {
      if (item.id === name) return
      item.handleClose()
    })
  }

  //關(guān)閉當(dāng)前tab頁
  const closeCurrent = (targetName) => {
    handleTabRemove(targetName)
  }

  //關(guān)閉左側(cè)tab頁
  const closeLeft = (targetName) => {
    //查找當(dāng)前點(diǎn)擊的tab頁所在位置
    let currentIndex = store.editableTabs.findIndex(
        (item) => item.name === targetName
    )
    //查找當(dāng)前激活標(biāo)簽頁index
    const activeIndex = store.editableTabs.findIndex((item) => item.name === store.editableTabsValue)
    //關(guān)閉左側(cè)tab頁
    store.editableTabs.splice(0, currentIndex)
    //刪除對(duì)應(yīng)的左側(cè)歷史路由
    store.tabRouterList.splice(0, currentIndex)
    //如果當(dāng)前關(guān)閉點(diǎn)擊的tab頁包含激活的tab頁,則將激活tab頁重置為當(dāng)前點(diǎn)擊的tab
    if (activeIndex < currentIndex) {
      //將當(dāng)前激活的tab頁改為當(dāng)前點(diǎn)擊的
      store.updateState(['editableTabsValue', targetName])
      //將激活菜單改為當(dāng)前點(diǎn)擊的
      store.updateState(['activeMenu', targetName])
      //路由跳轉(zhuǎn)到當(dāng)前點(diǎn)擊的tab頁
      //查詢當(dāng)前點(diǎn)擊的tab頁緩存路由參數(shù)
      let result = store.tabRouterList.find(item => item.path === targetName);
      //路由跳轉(zhuǎn)且?guī)蠈?duì)應(yīng)tab頁的參數(shù)
      router.push({ path: targetName, query: result.query })
    }
  }

  //關(guān)閉右側(cè)tab頁
  const closeRight = (targetName) => {
    //查找當(dāng)前點(diǎn)擊的tab頁所在位置
    let currentIndex = store.editableTabs.findIndex(
        (item) => item.name === targetName
    )
    //查找當(dāng)前激活標(biāo)簽頁index
    const activeIndex = store.editableTabs.findIndex((item) => item.name === store.editableTabsValue)
    //關(guān)閉右側(cè)tab頁
    store.editableTabs.splice(currentIndex + 1)
    //刪除對(duì)應(yīng)的右側(cè)歷史路由
    store.tabRouterList.splice(currentIndex + 1)
    //如果當(dāng)前關(guān)閉點(diǎn)擊的tab頁包含激活的tab頁,則將激活tab頁重置為當(dāng)前點(diǎn)擊的tab
    if (activeIndex > currentIndex) {
      //將當(dāng)前激活的tab頁改為當(dāng)前點(diǎn)擊的
      store.updateState(['editableTabsValue', targetName])
      //將激活菜單改為當(dāng)前點(diǎn)擊的
      store.updateState(['activeMenu', targetName])
      //路由跳轉(zhuǎn)到當(dāng)前點(diǎn)擊的tab頁
      //查詢當(dāng)前點(diǎn)擊的tab頁緩存路由參數(shù)
      let result = store.tabRouterList.find(item => item.path === targetName);
      //路由跳轉(zhuǎn)且?guī)蠈?duì)應(yīng)tab頁的參數(shù)
      router.push({ path: targetName, query: result.query })
    }
  }

  //關(guān)閉其他tab頁
  const closeOther = (targetName) => {
    //查找當(dāng)前點(diǎn)擊的tab頁所在位置
    let currentIndex = store.editableTabs.findIndex(
        (item) => item.name === targetName
    )
    //關(guān)閉其他標(biāo)簽頁
    store.editableTabs = [store.editableTabs[currentIndex]]
    //刪除除當(dāng)前點(diǎn)擊外的歷史路由
    store.tabRouterList = [store.tabRouterList[currentIndex]]
    //如果當(dāng)前點(diǎn)擊的不等于當(dāng)前激活的
    if (targetName !== store.editableTabsValue) {
      //將當(dāng)前激活的tab頁改為當(dāng)前點(diǎn)擊的
      store.updateState(['editableTabsValue', targetName])
      //將激活菜單改為當(dāng)前點(diǎn)擊的
      store.updateState(['activeMenu', targetName])
      //路由跳轉(zhuǎn)到當(dāng)前點(diǎn)擊的tab頁
      //查詢當(dāng)前點(diǎn)擊的tab頁緩存路由參數(shù)
      let result = store.tabRouterList.find(item => item.path === targetName);
      //路由跳轉(zhuǎn)且?guī)蠈?duì)應(yīng)tab頁的參數(shù)
      router.push({ path: targetName, query: result.query })
    }
  }

  //關(guān)閉全部tab頁
  const closeAll = () => {
    //清空tabs數(shù)組
    store.editableTabs.length = 0
    //清空歷史路由
    store.tabRouterList.length = 0
    //當(dāng)前選中tab頁設(shè)置為空
    store.updateState(['editableTabsValue', ''])
    //當(dāng)前激活菜單設(shè)置為空
    store.updateState(['activeMenu', ''])
    //跳轉(zhuǎn)到首頁
    router.push('home')
  }

  //處理tab標(biāo)簽x按鈕的移除
  function handleTabRemove(targetName) {
    //如果editableTabs列表不為空數(shù)組
    if (store.editableTabs.length > 0) {
      //如果當(dāng)前所在的tab頁路由地址與移除的tab頁名一樣,則移到前面一個(gè)tab頁且路由跳轉(zhuǎn)
      if (route.path === targetName) {
        let tabs = store.editableTabs
        tabs.forEach((tab, index) => {
          if (tab.name === targetName) {
            //獲取當(dāng)前tab的后一個(gè)或者前一個(gè)
            let nextTab = tabs[index + 1] || tabs[index - 1]
            //如果有值就移到它上面,沒有就是最后一個(gè)跳轉(zhuǎn)到首頁
            if (nextTab) {
              //根據(jù)name屬性進(jìn)行查詢當(dāng)前tab頁的緩存路由參數(shù)
              let result = store.tabRouterList.find(item => item.path === nextTab.name);
              //路由跳轉(zhuǎn)且?guī)蠈?duì)應(yīng)tab頁的參數(shù)
              router.push({ path: nextTab.name, query: result.query })
            } else {
              // 更改tab標(biāo)簽綁定值,選中選項(xiàng)卡的name
              store.updateState(['editableTabsValue', ''])
              // 更改當(dāng)前激活的菜單
              store.updateState(['activeMenu', ''])
              //當(dāng)刪除的是最后一個(gè)tab頁的時(shí)候,跳轉(zhuǎn)到首頁
              router.push('home')
            }
          }
        })
        //從editableTabs中移除當(dāng)前tab標(biāo)簽
        store.removeTab(targetName)
      } else {
        //從editableTabs中移除當(dāng)前tab標(biāo)簽
        store.removeTab(targetName)
      }
    }
  }

  //tab標(biāo)簽被選中時(shí)觸發(fā)的事件
  function handleTabClick(tab) {
    store.updateState(['activeMenu', tab.props.name])
    store.updateState(['editableTabsValue', tab.props.name])
    // 判斷當(dāng)前url地址和即將跳轉(zhuǎn)的是否一致,不一致進(jìn)行跳轉(zhuǎn),防止跳轉(zhuǎn)多次
    if (tab.props.name !== route.path) {
      // 根據(jù)name屬性進(jìn)行查詢
      let result = store.tabRouterList.find(item => item.path === tab.props.name);
      //路由跳轉(zhuǎn)且?guī)蠈?duì)應(yīng)tab頁的參數(shù)
      router.push({ path: tab.props.name, query: result.query })
    }
  }

  //退出登錄方法
  function logout() {

  }
</script>

<style lang="less" scoped>
  //設(shè)置高度
  :deep(.el-tabs__nav-scroll) {
    height: 60px;
  }

  //去掉el-tabs的邊框
  :deep(.el-tabs) {
    border: none;
  }

  .header {
    height: 62px;
    position: absolute;
    right: 30px;
    top: 0px;
    z-index: 1; //不設(shè)置這個(gè),el-down點(diǎn)擊出不來,被tab標(biāo)簽頁長(zhǎng)度擋住了
    display: flex;
    align-items: center; //垂直居中
  }

  //tab標(biāo)簽頁里面字體設(shè)置
  .label {
    color: #1B68B6 !important; //激活標(biāo)簽頁高亮
    font-size: 16px;
  }

  :deep(.el-tabs__item) {
    &:hover {
      span {
        color: #1B68B6 !important; //鼠標(biāo)移到標(biāo)簽頁高亮
      }
    }
  }
</style>

views文件下layout文件夾下的components文件夾下的appMain.vue代碼如下:

<!--通用布局頁面主體內(nèi)容-->
<template>
  <!-- 路由視圖對(duì)象 -->
  <router-view v-slot="{ Component }">
    <!--include主要解決關(guān)閉tab頁時(shí),同時(shí)銷毀該組件,防止再次重新打開時(shí)數(shù)據(jù)還在的情況。注意:組件name名必須和路由name名一致,否則會(huì)導(dǎo)致組件不緩存的情況。-->
    <keep-alive :include="tabsNames">
      <component :is="Component"></component>
    </keep-alive>
  </router-view>
</template>

<script setup name="AppMain">
  import useUserStore from "@/store/modules/userStore"
  import { computed } from "vue"
  const store = useUserStore()
  //將路由里面的name取出來作為一個(gè)數(shù)組
  const tabsNames = computed(() => store.tabRouterList.map((item) => item.name))
</script>

<style scoped>

</style>

這里之所以不把a(bǔ)ppMain.vue的路由視圖對(duì)象寫到navbar.vue里面的el-tabs里面,是因?yàn)閷懙絜l-tabs里面后,當(dāng)你打開多個(gè)tab頁的時(shí)候,當(dāng)你向后端發(fā)送請(qǐng)求時(shí),打開了多少個(gè)tab頁,就會(huì)重復(fù)發(fā)送多少個(gè)后端接口請(qǐng)求,所以這里將它拆開寫,el-tabs里面內(nèi)容實(shí)際是個(gè)空的。
通過element-plus里面的樣式讓它內(nèi)邊距為0,看著內(nèi)容像是放在了el-tabs里面。如下:

//讓el-tabs__content不顯示內(nèi)容
.el-tabs--border-card>.el-tabs__content{
  padding: 0px;
}

styles文件夾下的element-plus.less樣式代碼如下:

//移除頭部間距,讓寬度100%占滿
.el-header{
  --el-header-padding:0px;
  min-width: 1000px;
}
//未打開tab頁右邊背景色
.el-tabs__nav-scroll{
  background: #FFFFFF;
}
//設(shè)置內(nèi)容背景顏色
.el-main{
  background: #F2F6FB;
  min-width: 1000px;
}
//讓el-tabs__content不顯示內(nèi)容
.el-tabs--border-card>.el-tabs__content{
  padding: 0px;
}
//Tabs標(biāo)簽頁全局樣式
.el-tabs__item {
  height: 64px;
  font-size: 16px;
  background: #ffffff; //未選中Tabs頁背景顏色
}
//Tabs標(biāo)簽頁選中樣式
.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
  color: #1b68b6; //選中Tabs標(biāo)簽頁后字體顏色
  background-color: #e3edf7; //選中Tabs標(biāo)簽頁后背景顏色
}

瀏覽器結(jié)果如下,點(diǎn)擊多個(gè)菜單欄打開多個(gè)tab頁結(jié)果:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
點(diǎn)擊tab頁的同時(shí),菜單欄也來到對(duì)應(yīng)的選項(xiàng),如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
鼠標(biāo)放到tab頁上面的字體上面,然后鼠標(biāo)右鍵菜單,會(huì)顯示對(duì)應(yīng)的關(guān)閉菜單下拉選項(xiàng),如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
到這里tab頁相關(guān)的代碼就寫完了,但是有幾個(gè)問題需要注意,第一個(gè)問題就是你在瀏覽器上面直接輸入路由地址,它不會(huì)打開或者跳轉(zhuǎn)到對(duì)應(yīng)tab頁上面。第2個(gè)問題就是在實(shí)際開發(fā)中,如果頁面跳轉(zhuǎn)需要攜帶參數(shù)過去,當(dāng)你切換點(diǎn)擊tab頁的時(shí)候,參數(shù)會(huì)丟失問題。對(duì)于參數(shù)會(huì)丟失問題,所以才在userStore.js里面寫了一個(gè)tabRouterList屬性來存儲(chǔ)歷史路由及參數(shù)。

解決瀏覽器輸入地址時(shí)不會(huì)打開tab頁問題和切換tab頁時(shí)參數(shù)丟失問題

在router文件夾下面的index.js文件,將代碼修改為如下:

//引入router路由做頁面請(qǐng)求
import { createRouter,createWebHashHistory } from 'vue-router'
/* Layout通用組件 */
import Layout from '../views/layout/layout'
//引入pinia里面的state屬性和方法
import useUserStore from "@/store/modules/userStore"

const routes = [
  {path: '/404', component: () => import('@/views/404')},
  //必須要把組件放在Layout的children里面,才能在側(cè)邊欄的右側(cè)顯示頁面內(nèi)容,否則不加載通用架構(gòu)直接在當(dāng)前空白頁面渲染內(nèi)容,如:404頁面
  {
    path: '',
    component: Layout,
    redirect: '/home',
    children: [
      {
        path: 'home',
        name: 'home',
        component: () => import('@/views/home/index'),
        meta: {title: '首頁', icon: 'home'}
      },
      {
        path: 'test-management1',
        name: 'test-management1',
        component: () => import('@/views/test-management1/index'),
        meta: {title: '測(cè)試管理1', icon: 'systemManagement'}
      },
      {
        path: 'user-management',
        name: 'user-management',
        component: () => import('@/views/system-management/user-management'),
        meta: {title: '用戶管理', icon: 'userManagement'}
      },
      {
        path: 'role-management',
        name: 'role-management',
        component: () => import('@/views/system-management/role-management'),
        meta: {title: '角色管理', icon: 'roleManagement'}
      },
      {
        path: 'permission-management',
        name: 'permission-management',
        component: () => import('@/views/system-management/permission-management'),
        meta: {title: '權(quán)限管理', icon: 'permissionManagement'}
      },
      {
        path: 'password-management',
        name: 'password-management',
        component: () => import('@/views/system-management/password-management'),
        meta: {title: '密碼管理', icon: 'systemManagement'}
      },
      {
        path: 'test-management2',
        name: 'test-management2',
        component: () => import('@/views/test-management2/index'),
        meta: {title: '測(cè)試管理2', icon: 'systemManagement'}
      },
      {
        path: 'test-management5',
        name: 'test-management5',
        component: () => import('@/views/test-management5/index'),
        meta: {title: '測(cè)試管理5', icon: 'systemManagement'}
      }
    ]
  }
]

// 3. 創(chuàng)建路由實(shí)例并傳遞 `routes` 配置
const router = createRouter({
  // 4. 內(nèi)部提供了 history 模式的實(shí)現(xiàn)。為了簡(jiǎn)單起見,我們?cè)谶@里使用 hash 模式。
  history: createWebHashHistory(),
  routes, // `routes: routes` 的縮寫
})

//黑名單,在該黑名單里面的路由將不會(huì)動(dòng)態(tài)加載tab頁
const blackList=['/404','/home']

const handleToParams = (to) => {
  const route = {
    fullPath: to.fullPath,
    meta: to.meta,
    name: to.name,
    params: to.params,
    path: to.path,
    query: to.query,
  }
  return route
}

function  handleRouteInEditableTabs(to,store) {
  //判斷當(dāng)前路由的標(biāo)題是否已經(jīng)在editableTabs里,如果不在則動(dòng)態(tài)添加tab頁
  const indexInEditableTabs = store.editableTabs.findIndex(
      (item) => item.title === to.meta.title
  )
  //當(dāng)前路由的標(biāo)題已經(jīng)在editableTabs里
  if (indexInEditableTabs !== -1) {
    //判斷tabRouterList是否已經(jīng)存在相同的路由
    const indexInTabRouterList = store.tabRouterList.findIndex(
        (item) => item.name === to.name
    )
    //當(dāng)前路由的name已經(jīng)在tabRouterList里面
    if (indexInTabRouterList !== -1) {
      //根據(jù)當(dāng)前路由名稱找到對(duì)應(yīng)的歷史路由
      let result = store.tabRouterList.find(item => item.name === to.name)
      //在name相同但是路由的query參數(shù)不一樣,則替換為這個(gè)最新的(將對(duì)象轉(zhuǎn)為string字符串比較,即可判斷2個(gè)對(duì)象屬性與值是否完全一樣)
      let queryMatched=JSON.stringify(result.query) === JSON.stringify(to.query)
      //如果為false,則替換當(dāng)前路由參數(shù)
      if (!queryMatched) {
        //若存在,則從原始數(shù)組中移除該對(duì)象
        store.tabRouterList = store.tabRouterList.filter(
            (item) => item.name !== to.name
        )
        //重新添加這個(gè)新路由
        store.tabRouterList.push(handleToParams(to))
      }
    } else {
      //點(diǎn)擊菜單欄時(shí),如果不在則添加該路由
      store.tabRouterList.push(handleToParams(to))
    }
  } else {
    //判斷該路由是否在黑名單里面,不在則動(dòng)態(tài)添加tab頁
    if (!blackList.includes(to.path)) {
      //如果不在editableTabs里面,那么就在editableTabs里面添加這個(gè)tab頁
      store.editableTabs.push({
        title: to.meta.title,
        name: to.path,
        iconClass: to.meta.icon,
      })
      //點(diǎn)擊頁面中的某個(gè)按鈕進(jìn)行頁面跳轉(zhuǎn)的時(shí)候,如果不在則添加該路由里面部分字段
      store.tabRouterList.push(handleToParams(to))
    }
  }
}

//路由前置守衛(wèi)
router.beforeEach((to, from, next) => {
  //如果沒有匹配到路由,則跳轉(zhuǎn)到404頁面
  if (to.matched.length === 0) {
    next("/404")
  } else {
    //路由發(fā)生變化修改頁面title
    document.title = to.meta.title
    //使用pinia里面的全局狀態(tài)屬性
    const store = useUserStore()
    //更改tab標(biāo)簽綁定值,選中選項(xiàng)卡的name
    store.updateState(["editableTabsValue", to.path])
    //更改當(dāng)前激活的菜單
    store.updateState(["activeMenu", to.path])
    //動(dòng)態(tài)添加tab頁及tab頁切換時(shí)參數(shù)也跟著切換
    handleRouteInEditableTabs(to,store)
    next()
  }
})

//導(dǎo)出路由
export default router

瀏覽器結(jié)果如下,在瀏覽器直接輸入相應(yīng)路由,會(huì)自動(dòng)跳轉(zhuǎn)到對(duì)應(yīng)的tab,如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
輸入不存在的路由會(huì)直接跳轉(zhuǎn)到404頁面,如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
從用戶管理攜帶參數(shù)跳轉(zhuǎn)到角色管理,測(cè)試如下:
views文件夾下面的system-management文件夾下的user-management.vue代碼如下:

<template>
  <div>
    用戶管理頁面
    <el-button type="primary"
               @click="toRoleManagement(1)">
      跳轉(zhuǎn)到角色管理
    </el-button>
  </div>
</template>

<script setup name="user-management">
  import { useRouter } from "vue-router"

  //使用router跳轉(zhuǎn)路由
  const router=useRouter()

  const toRoleManagement = (id) => {
    //跳轉(zhuǎn)到郵單詳情里面
    router.push({ path: 'role-management', query: { id: id } })
  }
</script>

<style scoped>

</style>

views文件夾下面的system-management文件夾下的role-management.vue代碼如下:

<template>
  <div>角色管理頁面</div>
</template>

<script setup name="role-management">
  import {onActivated} from 'vue'
  import { useRoute } from "vue-router"
  //使用route接受路由傳過來的參數(shù)
  const route=useRoute()

  //每次頁面初始化時(shí)或者在郵件管理頁面點(diǎn)擊郵件詳情時(shí)執(zhí)行該方法
  onActivated(()=>{
    const id=route.query.id
    console.info("接受到的id=",id)
  })
</script>

<style scoped>

</style>

瀏覽器結(jié)果如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
點(diǎn)擊跳轉(zhuǎn)到角色管理按鈕結(jié)果如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
然后再次點(diǎn)擊用戶管理tab頁,如下:
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
再次點(diǎn)擊角色管理tab頁,發(fā)現(xiàn)參數(shù)依舊在沒有消失。問題解決。
Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn),前端,vue.js,javascript,前端,vue,html5
到這里Vue3+vite搭建基礎(chǔ)架構(gòu)的所有代碼就結(jié)束了。只需要根據(jù)實(shí)際需求添加對(duì)應(yīng)頁面即可。這里附上該示例項(xiàng)目的所有代碼地址,如果有需要,自行下載即可。
Vue3+vite搭建基礎(chǔ)架構(gòu)代碼鏈接:https://download.csdn.net/download/weixin_48040732/88855369文章來源地址http://www.zghlxwxcb.cn/news/detail-831541.html

到了這里,關(guān)于Vue3+vite搭建基礎(chǔ)架構(gòu)(11)--- 菜單欄功能和Tab頁功能實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Vue3+Vite項(xiàng)目搭建

    Vue3+Vite項(xiàng)目搭建

    技術(shù)棧:vue3+ts+vite+vue-router+element-plus+pinia 為什么選擇vite而不是vue-cli: vite 是一個(gè)基于 Vue3 單文件組件的非打包開發(fā)服務(wù)器,它做到了本地快速開發(fā)啟動(dòng): 快速的冷啟動(dòng),不需要等待打包操作; 即時(shí)的熱模塊更新,替換性能和模塊數(shù)量的解耦讓更新飛起; 真正的按需編譯,

    2024年02月08日
    瀏覽(33)
  • Vue3 + Vite 實(shí)現(xiàn)項(xiàng)目搭建

    Vue3 + Vite 實(shí)現(xiàn)項(xiàng)目搭建

    首先嘞,這個(gè)博文就是簡(jiǎn)單的記錄一下自己的對(duì) Vue3 的學(xué)習(xí),所以說呢,并不代表他是完全正確的。 創(chuàng)建 Vue3 項(xiàng)目有兩種常見的方式,一種是想 vue2 版本一樣使用腳手架工具創(chuàng)建,創(chuàng)建 vue3 項(xiàng)目的腳手架必須是4版本以上的,另一種方法就是使用 vite 創(chuàng)建,為什么使用 vite 呢

    2024年02月11日
    瀏覽(29)
  • vue3 項(xiàng)目搭建教程(基于create-vue,vite,Vite + Vue)

    vue3 項(xiàng)目搭建教程(基于create-vue,vite,Vite + Vue)

    目錄 一、搭建vue3 項(xiàng)目前提條件 二、通過create-vue搭建vue3 項(xiàng)目 三、搭建一個(gè) Vite 項(xiàng)目 四、構(gòu)建一個(gè) Vite + Vue 項(xiàng)目 五、打開Vue 項(xiàng)目管理器 六、Vite + Vue 項(xiàng)目目錄結(jié)構(gòu) 七、Vite.config.ts配置 前提條件 熟悉命令行 已安裝 16.0 或更高版本的 Node.js 同時(shí)按window+R鍵,輸入cmd,打開命令提

    2024年01月21日
    瀏覽(17)
  • vite+vue3+cesium環(huán)境搭建

    vite+vue3+cesium環(huán)境搭建

    1.創(chuàng)建一個(gè)Vite項(xiàng)目 npm create vite@latest 2.安裝cesium插件:vite-plugin-cesium npm i cesium vite-plugin-cesium vite -D 3、配置vite.config.js import cesium from \\\'vite-plugin-cesium\\\'; export default defineConfig({ plugins: [vue(),cesium()] }) 4、清空style.css中的樣式 5、配置App.vue 清空一切不需要的,設(shè)置樣式使得全屏 6、配

    2024年02月09日
    瀏覽(17)
  • 02_使用Vite搭建Vue3項(xiàng)目

    02_使用Vite搭建Vue3項(xiàng)目

    首先插件添加:Live Server、Vue - Official、Vue VSCode Snippets、別名路徑跳轉(zhuǎn) 官網(wǎng):Vite | 下一代的前端工具鏈 (vitejs.dev) 1.創(chuàng)建一個(gè)文件夾VueApp,運(yùn)行cmd轉(zhuǎn)到該目錄下,執(zhí)行命令:npm create vite@latest 2.然后轉(zhuǎn)到vuedemo目錄下命令:cd vuedemo, 3.執(zhí)行命令:npm install。文件夾內(nèi)會(huì)新添加no

    2024年04月08日
    瀏覽(25)
  • 前端VUE3+Vite +UniAPP-- 框架搭建

    前端VUE3+Vite +UniAPP-- 框架搭建

    除了HBuilderX可視化界面,也可以使用 cli 腳手架,可以通過 vue-cli 創(chuàng)建 uni-app 項(xiàng)目。 全局安裝 vue-cli 官網(wǎng) 配置tailwindcss插件 官網(wǎng) 在 tailwind.config.js 配置文件中添加所有模板文件的路徑。 將加載 Tailwind 的指令添加到你的 CSS 文件中 在你的主 CSS 文件中通過 @tailwind 指令添加每一

    2024年02月11日
    瀏覽(17)
  • vite+vue3搭建的工程熱更新失效問題

    vite+vue3搭建的工程熱更新失效問題

    ? ? ? ?前段時(shí)間開發(fā)新的項(xiàng)目,由于沒有技術(shù)上的限制,所以選擇了vite+vue3+ts來開發(fā)新的項(xiàng)目,一開始用vite來開發(fā)新項(xiàng)目過程挺順利,確實(shí)比vue2+webpack的項(xiàng)目高效些(為什么選擇vite),但是過了一段時(shí)間后,不過怎么操作頁面修改頁面都無法及時(shí)刷新預(yù)覽頁面,各種糾結(jié)。

    2023年04月09日
    瀏覽(20)
  • Vite4+Typescript+Vue3+Pinia 從零搭建(3) - vite配置

    Vite4+Typescript+Vue3+Pinia 從零搭建(3) - vite配置

    項(xiàng)目代碼同步至碼云 weiz-vue3-template 關(guān)于vite的詳細(xì)配置可查看 vite官方文檔,本文簡(jiǎn)單介紹vite的常用配置。 項(xiàng)目初建后, vite.config.ts 的默認(rèn)內(nèi)容如下: 比如,修改 App.vue : 根目錄下新建 .env 、 .env.development 、 .env.production 三個(gè)文件。 .env 文件內(nèi)新增內(nèi)容: .env.development 文件內(nèi)

    2024年02月05日
    瀏覽(86)
  • 07. vue3+vite+qiankun搭建微應(yīng)用前端框架,并接入vue3微應(yīng)用

    07. vue3+vite+qiankun搭建微應(yīng)用前端框架,并接入vue3微應(yīng)用

    因?yàn)闃I(yè)務(wù)系統(tǒng)接入的需要,決定將一個(gè)vue3+vite+ts的主應(yīng)用系統(tǒng),改造成基于qiankun的微應(yīng)用架構(gòu)。此文記錄了改造的過程及vue3微應(yīng)用接入的種種問題。 網(wǎng)上有很多關(guān)于微應(yīng)用改造的案例,但很多都沒寫部署之后什么情況。寫了部署的,沒有實(shí)操部署在二級(jí)目錄、三級(jí)目錄是什

    2024年01月16日
    瀏覽(18)
  • 2023 最新最細(xì) vite+vue3+ts 多頁面項(xiàng)目架構(gòu),建議收藏備用!

    2023 最新最細(xì) vite+vue3+ts 多頁面項(xiàng)目架構(gòu),建議收藏備用!

    本文教程 github地址 、碼云。 如果對(duì)你有幫助,希望能點(diǎn)個(gè)star ?????? 萬分感謝?????? 不久前我司需要重新部署一個(gè)前端項(xiàng)目,由我來負(fù)責(zé)這個(gè)項(xiàng)目的搭建。因?yàn)檫@個(gè)項(xiàng)目是需要和app混合開發(fā)的h5頁面,包括以后可能會(huì)做一些運(yùn)營h5,所以自然不能采用常規(guī)的 SPA單頁

    2024年02月06日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包