封装修改完成header头部导航栏组件为动态tree渲染
This commit is contained in:
parent
3a561a504e
commit
e2e5e73d04
97
components/header-nav.vue
Normal file
97
components/header-nav.vue
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="h-100"
|
||||||
|
:class="level === 0 ? 'd-flex align-items-center' : ''"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(item,index) in nodes"
|
||||||
|
:key="index"
|
||||||
|
class="nav-link-item d-flex align-items-center justify-content-center"
|
||||||
|
>
|
||||||
|
<nuxt-link
|
||||||
|
:to="item.to"
|
||||||
|
v-if="item.children.length === 0"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</nuxt-link>
|
||||||
|
<b-nav-item-dropdown
|
||||||
|
v-else
|
||||||
|
:id="item.id"
|
||||||
|
:text="item.label"
|
||||||
|
right
|
||||||
|
@show="isDropdown=true"
|
||||||
|
v-model="isDropdown"
|
||||||
|
@hide="dropdownHide($event, item)"
|
||||||
|
>
|
||||||
|
<header-nav
|
||||||
|
:nodes="item.children"
|
||||||
|
:level="level + 1"
|
||||||
|
/>
|
||||||
|
</b-nav-item-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'HeaderNav',
|
||||||
|
props: {
|
||||||
|
level: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isDropdown: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
dropdownHide(e, item) {
|
||||||
|
if (this.isDropdown) {
|
||||||
|
e.preventDefault()
|
||||||
|
this.isDropdown = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@mixin activeNav {
|
||||||
|
&:hover {
|
||||||
|
position: relative;
|
||||||
|
color: #015fe8;
|
||||||
|
background: linear-gradient( 180deg, rgba(1,95,232,0) 0%, rgba(1,95,232,0.08) 100%);
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: .125rem;
|
||||||
|
background: #015fe8;
|
||||||
|
}
|
||||||
|
>a {
|
||||||
|
color: #015fe8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.nav-link-item {
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 1.4375rem;
|
||||||
|
>a {
|
||||||
|
color: #151516;
|
||||||
|
}
|
||||||
|
@include activeNav;
|
||||||
|
}
|
||||||
|
.active-item {
|
||||||
|
@include activeNav;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -4,14 +4,7 @@
|
|||||||
<img src="~assets/image/logo.png" width="265px" :alt="$t('index.corporateName')">
|
<img src="~assets/image/logo.png" width="265px" :alt="$t('index.corporateName')">
|
||||||
|
|
||||||
<nav class="d-md-flex align-items-center">
|
<nav class="d-md-flex align-items-center">
|
||||||
<nuxt-link
|
<HeaderNav :nodes="menuTree" />
|
||||||
class="nav-link-item d-flex align-items-center"
|
|
||||||
:to="item.href"
|
|
||||||
v-for="(item,index) in menuList"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
{{ item.name }}
|
|
||||||
</nuxt-link>
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
@ -48,11 +41,11 @@
|
|||||||
<nav class="mob-nav hide_scroll_bar d-flex align-items-center">
|
<nav class="mob-nav hide_scroll_bar d-flex align-items-center">
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
class="nav-link-item d-flex align-items-center"
|
class="nav-link-item d-flex align-items-center"
|
||||||
:to="item.href"
|
:to="item.to"
|
||||||
v-for="(item,index) in menuList"
|
v-for="(item,index) in menuTree"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
{{ item.name }}
|
{{ item.label }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
@ -62,23 +55,32 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapState } from 'vuex';
|
||||||
import MenuDrawer from './menu-drawer.vue';
|
import MenuDrawer from './menu-drawer.vue';
|
||||||
|
import HeaderNav from './header-nav.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { MenuDrawer },
|
components: {
|
||||||
|
MenuDrawer,
|
||||||
|
HeaderNav
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchVal: '',
|
searchVal: '',
|
||||||
menuList: [
|
// menuList: [
|
||||||
{ name: this.$t('menu.Home'), href: '/' },
|
// { name: this.$t('menu.Home'), href: '/' },
|
||||||
{ name: this.$t('menu.AboutUs'), href: '/abou-us' },
|
// { name: this.$t('menu.AboutUs'), href: '/abou-us' },
|
||||||
{ name: this.$t('menu.Products'), href: '/products' },
|
// { name: this.$t('menu.Products'), href: '/products' },
|
||||||
{ name: this.$t('menu.News'), href: '/news' },
|
// { name: this.$t('menu.News'), href: '/news' },
|
||||||
{ name: this.$t('menu.Exhibition'), href: '/exhibition' },
|
// { name: this.$t('menu.Exhibition'), href: '/exhibition' },
|
||||||
{ name: this.$t('menu.ContactUs'), href: '/contact-us' },
|
// { name: this.$t('menu.ContactUs'), href: '/contact-us' },
|
||||||
{ name: this.$t('menu.Feedback'), href: '/feedback' },
|
// { name: this.$t('menu.Feedback'), href: '/feedback' },
|
||||||
]
|
// ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(['menuTree'])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -110,38 +112,8 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@mixin activeNav {
|
|
||||||
&:hover {
|
|
||||||
position: relative;
|
|
||||||
color: #015fe8;
|
|
||||||
background: linear-gradient( 180deg, rgba(1,95,232,0) 0%, rgba(1,95,232,0.08) 100%);
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: .125rem;
|
|
||||||
background: #015fe8;
|
|
||||||
}
|
|
||||||
>a {
|
|
||||||
color: #015fe8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nav {
|
nav {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
.nav-link-item {
|
|
||||||
height: 100%;
|
|
||||||
padding: 0 1.4375rem;
|
|
||||||
>a {
|
|
||||||
color: #151516;
|
|
||||||
}
|
|
||||||
@include activeNav;
|
|
||||||
}
|
|
||||||
.active-item {
|
|
||||||
@include activeNav;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.header-box {
|
.header-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
4
env.js
4
env.js
@ -8,8 +8,8 @@ module.exports = {
|
|||||||
// 开发环境 接口请求地址 (http)或(https)://www.a.com(换成你的域名)/api
|
// 开发环境 接口请求地址 (http)或(https)://www.a.com(换成你的域名)/api
|
||||||
dev: {
|
dev: {
|
||||||
MODE: 'dev',
|
MODE: 'dev',
|
||||||
// VUE_APP_API_URL: 'http://122.51.230.86:8099/',
|
VUE_APP_API_URL: 'http://122.51.230.86:8099/',
|
||||||
VUE_APP_API_URL: 'http://192.168.1.4:8099/',
|
// VUE_APP_API_URL: 'http://192.168.1.4:8099/',
|
||||||
VUE_APP_WEBSOCKET: 'ws://localhost:8099/ws/asset/'
|
VUE_APP_WEBSOCKET: 'ws://localhost:8099/ws/asset/'
|
||||||
},
|
},
|
||||||
// 生产环境 接口请求地址 (http)或(https)://www.a.com(换成你的域名)/api 非独立部署默认为空
|
// 生产环境 接口请求地址 (http)或(https)://www.a.com(换成你的域名)/api 非独立部署默认为空
|
||||||
|
|||||||
7
middleware/header.js
Normal file
7
middleware/header.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export default async function ({
|
||||||
|
$axios,
|
||||||
|
store
|
||||||
|
}) {
|
||||||
|
const menuTree = await $axios.$get('/web/category')
|
||||||
|
store.commit('SET_MENU_TREE', menuTree)
|
||||||
|
}
|
||||||
@ -78,7 +78,7 @@ export default {
|
|||||||
icons: false
|
icons: false
|
||||||
},
|
},
|
||||||
router: {
|
router: {
|
||||||
middleware: ['i18n', 'footer']
|
middleware: ['i18n', 'footer', 'header']
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
** Build configuration
|
** Build configuration
|
||||||
|
|||||||
17369
package-lock.json
generated
17369
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,14 @@
|
|||||||
|
const routeMap = {
|
||||||
|
'dym': 'separate', // 单页面
|
||||||
|
'xp': 'inquiry', // 询盘栏目
|
||||||
|
'wz': 'article', // 文章栏目
|
||||||
|
'cp': 'product' // 产品栏目
|
||||||
|
}
|
||||||
|
|
||||||
export const state = () => ({
|
export const state = () => ({
|
||||||
locales: ['en', 'zh'],
|
locales: ['en', 'zh'],
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
|
menuTree: [],
|
||||||
footerInfo: {}
|
footerInfo: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -12,6 +20,25 @@ export const mutations = {
|
|||||||
},
|
},
|
||||||
SET_FOOTER_INFO (state, info) {
|
SET_FOOTER_INFO (state, info) {
|
||||||
state.footerInfo = info
|
state.footerInfo = info
|
||||||
|
},
|
||||||
|
SET_MENU_TREE (state, tree) {
|
||||||
|
state.menuTree = [
|
||||||
|
{label:'Home', to: '/', children: []}
|
||||||
|
]
|
||||||
|
const fn = (list) => {
|
||||||
|
list.forEach(item => {
|
||||||
|
if (item.catgLevel===1) {
|
||||||
|
item.to = `/${routeMap[item.catgType]}?catgId=${item.id}`
|
||||||
|
} else {
|
||||||
|
item.to = `/${routeMap[item.catgType]}/${item.id}?catgId=${item.maxParentId}`
|
||||||
|
}
|
||||||
|
if (item.children.length) {
|
||||||
|
fn(item.children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn(tree)
|
||||||
|
state.menuTree = [...state.menuTree, ...tree]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user