Vue3项目 网易严选_学习笔记

Vue3项目 网易严选_第一天

主要内容

  • 项目搭建
  • vuex基础
  • 路由设计
  • 首页顶部和底部布局

学习目标

知识点要求
项目搭建掌握
vuex基础掌握
路由设计掌握
首页顶部和底部布局掌握

一、项目搭建

1.1 创建项目

  1. vue create vue-wangyi
  2. 选择vue3.0版本

1.2 目录调整

大致步骤:

  • 删除无用代码和文件
  • 完善项目的基础结构
  • 读懂默认生成的代码

落的代码:	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2m8kPIaZ-1663513268468)(images\jiegou.png)]

注意:以上结构目录及供参考

二、Vuex基础

安装:

npm install vuex@next --save

2.1 定义模块

export default createStore({
  state: {
    username: 'zs'
  },
  getters: {
    newName (state) {
      return state.username + '!!!'
    }
  },
  //同步请求
  mutations: {
    updateName (state) {
      state.username = 'ls'
    }
  },
  //异步请求,内部调用同步请求
  actions: {
    updateName (ctx) {
      // 发请求
      setTimeout(() => {
        ctx.commit('updateName')
      }, 1000)
    }
  },
  modules: {

  }
})

使用

<template>
  <!-- vue2.0需要根元素,vue3.0可以是代码片段 Fragment -->
  <div>
    App
    <!-- 1. 使用根模块state的数据   -->
    <p>{{$store.state.username}}</p>
    <!-- 2. 使用根模块getters的数据   -->
    <p>{{$store.getters['newName']}}</p>
    <button @click="mutationsFn">mutationsFn</button>
  </div>
</template>
<script>
import { useStore } from 'vuex'
export default {
  name: 'App',
  setup () {
    // 使用vuex仓库
    const store = useStore()
    // 1. 使用根模块state的数据
    console.log(store.state.username)
    // 2. 使用根模块getters的数据
    console.log(store.getters.newName)
    const mutationsFn = () => {
      // 3. 提交根模块mutations函数
      // store.commit('updateName')
      // 4. 调用根模块actions函数
      store.dispatch('updateName')
    }
    return { mutationsFn }
  }
}
</script>

2.2 modules (分模块)

存在两种情况

​ 默认的模块,state 区分模块,其他 getters mutations actions 都在全局。

​ 带命名空间 namespaced: true 的模块,所有功能区分模块,更高封装度和复用。

import { createStore } from 'vuex'

const moduleA = {
  // 子模块state建议写成函数
  state: () => {
    return {
      username: '模块A'
    }
  },
  getters: {
    changeName (state) {
      return state.username + 'AAAAAA'
    }
  }
}

const moduleB = {
  // 带命名空间的模块
  namespaced: true,
  // 子模块state建议写成函数
  state: () => {
    return {
      username: '模块B'
    }
  },
  getters: {
    changeName (state) {
      return state.username + 'BBBBBB'
    }
  },
  mutations: {
    // 修改名字的mutation
    update (state) {
      state.username = 'BBBB' + state.username
    }
  },
  actions: {
    update ({ commit }) {
      // 假设请求
      setTimeout(() => {
        commit('update')
      }, 2000)
    }
  }
}

// 创建vuex仓库并导出
export default createStore({
  state: {
    // 数据
    person: [
      { id: 1, name: 'tom', gender: '男' },
      { id: 2, name: 'lucy', gender: '女' },
      { id: 3, name: 'jack', gender: '男' }
    ]
  },
  mutations: {
    // 改数据函数
  },
  actions: {
    // 请求数据函数
  },
  modules: {
    // 分模块
    a: moduleA,
    b: moduleB
  },
  getters: {
    // vuex的计算属性
    boys: (state) => {
      return state.person.filter(p => p.gender === '男')
    }
  }
})

使用:

<template>
 <div>APP组件</div>
 <ul>
   <li v-for="item in $store.getters.boys" :key="item.id">{{item.name}}</li>
 </ul>
 <!-- 使用模块A的username -->
 <p>A的username --- {{$store.state.a.username}}</p>
 <p>A的changeName --- {{$store.getters.changeName}}</p>
 <hr>
 <p>B的username --- {{$store.state.b.username}}</p>
 <p>B的changeName --- {{$store.getters['b/changeName']}}</p>
 <button @click="$store.commit('b/update')">修改username</button>
 <button @click="$store.dispatch('b/update')">异步修改username</button>
</template>

2.3 vuex-持久化

在开发的过程中,像用户信息(名字,头像,token)需要vuex中存储且需要本地存储。

再例如,购物车如果需要未登录状态下也支持,如果管理在vuex中页需要存储在本地。

我们需要category模块存储分类信息,但是分类信息不需要持久化。

1)首先:我们需要安装一个vuex的插件vuex-persistedstate来支持vuex的状态持久化。

npm i vuex-persistedstate

2)然后:在src/store 文件夹下新建 modules 文件,在 modules 下新建 user.jscart.js

src/store/modules/user.js

// 用户模块
export default {
  namespaced: true,
  state () {
    return {
      // 用户信息
      profile: {
        id: '',
        avatar: '',
        nickname: '',
        account: '',
        mobile: '',
        token: ''
      }
    }
  },
  mutations: {
    // 修改用户信息,payload就是用户信息对象
    setUser (state, payload) {
      state.profile = payload
    }
  }
}

src/store/modules/cart.js

// 购物车状态
export default {
  namespaced: true,
  state: () => {
    return {
      list: []
    }
  }
}

src/store/modules/category.js

// 分类模块
export default {
  namespaced: true,
  state () {
    return {
      // 分类信息集合
      list: []
    }
  }
}

3)继续:在 src/store/index.js 中导入 user cart 模块。

import { createStore } from 'vuex'

import user from './modules/user'
import cart from './modules/cart'
import cart from './modules/category'

export default createStore({
  modules: {
    user,
    cart,
    category
  }
})

4)最后:使用vuex-persistedstate插件来进行持久化

import { createStore } from 'vuex'
+import createPersistedstate from 'vuex-persistedstate'

import user from './modules/user'
import cart from './modules/cart'
import category from './modules/category'

export default createStore({
  modules: {
    user,
    cart,
    category
  },
+  plugins: [
+    createPersistedstate({
+      key: 'pc-store',
+      paths: ['user', 'cart']
+    })
+  ]
})

注意:

===> 默认是存储在localStorage中

===> key是存储数据的键名

===> paths是存储state中的那些数据,如果是模块下具体的数据需要加上模块名称,如user.token

===> 修改state后触发才可以看到本地存储数据的的变化。

测试: user模块定义一个mutation在main.js去调用下,观察浏览器application的localStorage下数据。

src/App.js

<template>
  <div class="container">
    <!-- 修改数据,测试是否持久化 -->
    App {{$store.state.user.profile.account}}
    <button @click="$store.commit('user/setUser',{account:'zhoujielun'})">设置用户信息</button>
  </div>
</template>
<script>
export default {
  name: 'App'
}
</script>

三、路由设计

3.1 路由布局

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZZaVeLrA-1663513268469)(images\luyou.png)]

3.2 路由基础实现

路由文件index.js

import { createRouter, createWebHashHistory } from 'vue-router'

//异步加载组件
const Layout = ()=>import('@/views/Layout.vue')
const Home = ()=>import('@/views/home')
import TopCategory from '@/views/category'
import SubCategory from '@/views/category/sub'

const routes = [
    {
      path:'/',
      component:Layout,
      children:[
        { path:'/',component:Home},
        { path: '/category/:id', component: TopCategory },
        { path: '/category/sub/:id', component: SubCategory }
      ]
    }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

App.vue

<template>
  <!-- 一级路由 -->
  <router-view />
</template>
<script>
export default {
  setup() {},
};
</script>

<style lang="less">
</style>

一级路由布局容器 src/views/Layout.vue

<template>
  <nav>顶部通栏</nav>
  <header>头部</header>
  <main>
    <!-- 二级路由 -->
    <router-view></router-view>
  </main>
  <footer>底部</footer>
</template>

<script>
export default {
  name: 'xtx-layout'
}
</script>

<style scoped lang='less'></style>

二级路由首页组件 src/views/home/index.vue

<template>
  <div class='xtx-home-page'>
    首页
  </div>
</template>

<script>
export default {
  name: 'xtx-home-page'
}
</script>

<style scoped lang='less'></style>

3.3 样式配置

变量 src/assets/styles/variables.less

// 主题
@xtxColor:#27BA9B;
// 辅助
@helpColor:#E26237;
// 成功
@sucColor:#1DC779;
// 警告
@warnColor:#FFB302;
// 价格
@priceColor:#CF4444;

混入 src/assets/styles/mixins.less

// 鼠标经过上移阴影动画
.hoverShadow () {
  transition: all .5s;
  &:hover {
    transform: translate3d(0,-3px,0);
    box-shadow: 0 3px 8px rgba(0,0,0,0.2);
  }
}

less混入就是,申明一段css代码(选择器包裹的代码)或者函数,在其他css选择器调用,可复用包裹的代码

完成自动注入公用变量和混入

四、首页顶部和底部布局

4.1 顶部通栏布局

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsWipuCv-1663513268469)(images\top.png)]

代码演示:

<template>
  <nav class="app-topnav">
    <div class="container">
      <ul>
        <template v-if="profile.token">
          <li>
            <a href="javascript:;"><i class="iconfont icon-user"></i>周杰伦</a>
          </li>
          <li><a href="javascript:;">退出登录</a></li>
        </template>
        <template v-else>
          <li><a href="javascript:;">请先登录</a></li>
          <li><a href="javascript:;">免费注册</a></li>
        </template>

        <li><a href="javascript:;">我的订单</a></li>
        <li><a href="javascript:;">会员中心</a></li>
        <li><a href="javascript:;">帮助中心</a></li>
        <li><a href="javascript:;">关于我们</a></li>
        <li>
          <a href="javascript:;"><i class="iconfont icon-phone"></i>手机版</a>
        </li>
      </ul>
    </div>
  </nav>
</template>
<script>
import { computed } from "@vue/runtime-core";
import { useStore } from "vuex";

export default {
  name: "AppTopnav",
  setup() {
    const store = useStore();
    const profile = computed(() => {
      return store.state.user.profile;
    });

    return { profile };
  },
};
</script>
<style scoped lang="less">
.app-topnav {
  background: #333;
  ul {
    display: flex;
    height: 53px;
    justify-content: flex-end;
    align-items: center;
    li {
      a {
        padding: 0 15px;
        color: #cdcdcd;
        line-height: 1;
        display: inline-block;
        i {
          font-size: 14px;
          margin-right: 2px;
        }
        &:hover {
          color: @xtxColor;
        }
      }
      ~ li {
        a {
          border-left: 2px solid #666;
        }
      }
    }
  }
}
</style>

布局界面

<template>
  <div>
    <!-- 顶部区域 -->
    <AppTopnav/>
  </div>
</template>
<script>
import AppTopnav from '@/components/app-topnav.vue';

export default {
  name:'Layout',
  components:{
    AppTopnav,
  },
};
</script>
<style lang="less" scoped>
.main{
  min-height: 500px;
}
.active{
  color: @xtxColor;
  .hoverShadow()
}
</style>

4.2 头部布局

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZAcockDl-1663513268469)(images\header.png)]

代码演示:

<template>
  <header class="app-header">
    <div class="container">
      <!-- 顶部区域 -->
      <div class="app-top">
        <h1 class="logo">
          <RouterLink to="/">
            <img src="../assets/images/logo.png" alt="" />
          </RouterLink>
        </h1>
        <div class="center">
          <div class="center-search">
            <input type="text" />
            <div class="btn">搜索</div>
          </div>
          <ul class="navs">
            <li><a href="#">美食</a></li>
            <li><a href="#">餐厨</a></li>
            <li><a href="#">艺术</a></li>
            <li><a href="#">电器</a></li>
            <li><a href="#">居家</a></li>
            <li><a href="#">洗护</a></li>
            <li><a href="#">孕婴</a></li>
            <li><a href="#">服装</a></li>
            <li><a href="#">杂货</a></li>
          </ul>
        </div>

        <div class="search">
          <i class="iconfont icon-search"></i>
          <input type="text" placeholder="搜一搜" />
        </div>
        <div class="cart">
          <a class="curr" href="#">
            <i class="iconfont icon-cart"></i><em>2</em>
          </a>
        </div>
      </div>
      <!-- 二级导航 -->
      <div class="app-nav">
          <AppHeaderNav/>
      </div>
    </div>
  </header>
</template>

<script>
import AppHeaderNav from './app-header-nav.vue';

export default {
  name: "AppHeader",
  components:{
    AppHeaderNav
  }
};
</script>

<style scoped lang='less'>
.app-header {
  background: #fff;
  .app-top {
    display: flex;
    align-items: center;
  }
  .logo {
    width: 200px;
    a {
      display: block;
      height: 100px;
      width: 100%;
      margin-top: 15px;
    }
  }
  .center {
    position: relative;
    margin-top: 26px;
    flex: 1;
    .center-search {
      width: 532px;
      float: right;
      input {
        height: 38px;
        line-height: 38px;
        padding-top: 2px;
        padding-bottom: 2px;
        border: 1px solid #cc9756;
        border-bottom-left-radius: 19px;
        border-top-left-radius: 19px;
        font-size: 14px;
        width: 442px;
        padding-left: 38px;
      }
      .btn {
        width: 90px;
        height: 38px;
        background-color: #cc9756;
        border-top-right-radius: 19px;
        border-bottom-right-radius: 19px;
        cursor: pointer;
        float: right;
        color: #fff;
        line-height: 38px;
        text-align: center;
        font-size: 16px;
        letter-spacing: 1px;
      }
    }
  }
  // 底部导航---------------------
  .app-nav{
     height: 40px;
    .navs{
      float: left;
      li{
        line-height: 40px;
        font-weight: bold;
        a{
          border-right: 0;
           color: #000;
        }
      }
    }
  }
  //-----------------------------
  .navs {
    width: 520px;
    display: flex;
    justify-content: space-around;
    float: right;
    padding-right: 80px;
    li {
      line-height: 32px;
      text-align: center;
      a {
        font-size: 12px;
        line-height: 12px;
        padding: 0 10px;
        display: inline-block;
        border-right: 1px solid #ccc;
        color: #999;
      }
      &:hover {
        a {
          color: @xtxColor;
        }
      }
    }
    li:last-child a {
      border-right: 0;
    }
  }
  .search {
    width: 170px;
    height: 32px;
    position: relative;
    border-bottom: 1px solid #e7e7e7;
    line-height: 32px;
    .icon-search {
      font-size: 18px;
      margin-left: 5px;
    }
    input {
      width: 140px;
      padding-left: 5px;
      color: #666;
    }
  }
  .cart {
    width: 50px;
    .curr {
      height: 32px;
      line-height: 32px;
      text-align: center;
      position: relative;
      display: block;
      .icon-cart {
        font-size: 22px;
      }
      em {
        font-style: normal;
        position: absolute;
        right: 0;
        top: 0;
        padding: 1px 6px;
        line-height: 1;
        background: @helpColor;
        color: #fff;
        font-size: 12px;
        border-radius: 10px;
        font-family: Arial;
      }
    }
  }
}
</style>

二级导航

<template>
  <ul class="app-header-nav">
    <li><RouterLink to="/">首页</RouterLink></li>
    	<li><a href="#">美食</a></li>
        <li><a href="#">餐厨</a></li>
        <li><a href="#">艺术</a></li>
        <li><a href="#">电器</a></li>
        <li><a href="#">居家</a></li>
        <li><a href="#">洗护</a></li>
        <li><a href="#">孕婴</a></li>
        <li><a href="#">服装</a></li>
        <li><a href="#">杂货</a></li>
  </ul>
</template>

<script>
export default {
  name: "AppHeaderNav",
  }
};
</script>
<style scoped lang='less'>
.app-header-nav {
  width: 1240px;
  display: flex;
  justify-content: space-around;
  position: relative; 
  z-index: 998;  
  > li {
    > a {
      font-size: 14px;
      line-height: 40px;
      font-weight: bold;
      height: 40px;
      display: inline-block;
    }
    .router-link-exact-active{
       color: @xtxColor;
        border-bottom: 2px solid @xtxColor;
    }
    &:hover {  
      > a {
        color: @xtxColor;
        border-bottom: 2px solid @xtxColor;
      }
      > .layer {
        height: 132px;
        opacity: 0;
      }
      .active{
        opacity: 1;
      }
    }
  }
}
.layer {
  width: 1240px;
  background-color: #fff;
  position: absolute;
  left: 0px;
  top: 42px;
  height: 0;
  overflow: hidden;
  opacity: 0;
  box-shadow: 0 0 5px #ccc;
  transition: all .2s .1s;
  ul {
    display: flex;
    flex-wrap: wrap;
    padding: 0 70px;
    align-items: center;
    height: 132px;
    li {
      width: 110px;
      text-align: center;
      img {
        width: 60px;
        height: 60px;
      }
      p {
        padding-top: 10px;
      }
      &:hover {
        p {
          color: @xtxColor;
        }
      }
    }
  }
}
</style>

4.3 底部布局

​	效果展示[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZgCxLlIz-1663513268470)(images\footer.png)]

代码展示

<template>
  <footer class="app-footer">
    <!-- 联系我们 -->
    <div class="contact">
      <div class="container">
        <dl>
          <dt>客户服务</dt>
          <dd><i class="iconfont icon-kefu"></i> 在线客服</dd>
          <dd><i class="iconfont icon-wenti1"></i> 问题反馈</dd>
        </dl>
        <dl>
          <dt>关注我们</dt>
          <dd><i class="iconfont icon-weixin"></i> 公众号</dd>
          <dd><i class="iconfont icon-weibo"></i> 微博</dd>
        </dl>
        <dl>
          <dt>下载APP</dt>
          <dd class="qrcode"><img src="../assets/images/saoma.png" /></dd>
          <dd class="download">
            <span>扫描二维码</span>
            <span>立马下载APP</span>
            <a href="javascript:;">下载页面</a>
          </dd>
        </dl>
        <dl>
          <dt>服务热线</dt>
          <dd class="hotline">400-0000-000 <small>周一至周日 8:00-18:00</small></dd>
        </dl>
      </div>
    </div>
    <!-- 其它 -->
    <div class="extra">
      <div class="container">
        <div class="slogan">
          <a href="javascript:;">
            <i class="iconfont icon-footer01"></i>
            <span>价格亲民</span>
          </a>
          <a href="javascript:;">
            <i class="iconfont icon-footer02"></i>
            <span>物流快捷</span>
          </a>
          <a href="javascript:;">
            <i class="iconfont icon-footer03"></i>
            <span>品质新鲜</span>
          </a>
        </div>
        <!-- 版权信息 -->
        <div class="copyright">
          <p>
            <a href="javascript:;">关于我们</a>
            <a href="javascript:;">帮助中心</a>
            <a href="javascript:;">售后服务</a>
            <a href="javascript:;">配送与验收</a>
            <a href="javascript:;">商务合作</a>
            <a href="javascript:;">搜索推荐</a>
            <a href="javascript:;">友情链接</a>
          </p>
          <p>CopyRight © 网易严选</p>
        </div>
      </div>
    </div>
  </footer>
</template>

<script>
export default {
  name: 'AppFooter'
}
</script>

<style scoped lang='less'>
.app-footer {
  overflow: hidden;
  background-color: #f5f5f5;
  padding-top: 20px;
  .contact {
    background: #fff;
    .container {
      padding: 60px 0 40px 25px;
      display: flex;
    }
    dl {
      height: 190px;
      text-align: center;
      padding: 0 72px;
      border-right: 1px solid #f2f2f2;
      color: #999;
      &:first-child {
        padding-left: 0;
      }
      &:last-child {
        border-right: none;
        padding-right: 0;
      }
    }
    dt {
      line-height: 1;
      font-size: 18px;
    }
    dd {
      margin: 36px 12px 0 0;
      float: left;
      width: 92px;
      height: 92px;
      padding-top: 10px;
      border: 1px solid #ededed;
      .iconfont {
        font-size: 36px;
        display: block;
        color: #666;
      }
      &:hover {
        .iconfont {
          color: @xtxColor;
        }
      }
      &:last-child {
        margin-right: 0;
      }
    }
    .qrcode {
      width: 92px;
      height: 92px;
      padding: 7px;
      border: 1px solid #ededed;
    }
    .download {
      padding-top: 5px;
      font-size: 14px;
      width: auto;
      height: auto;
      border: none;
      span {
        display: block;
      }
      a {
        display: block;
        line-height: 1;
        padding: 10px 25px;
        margin-top: 5px;
        color: #fff;
        border-radius: 2px;
        background-color: @xtxColor;
      }
    }
    .hotline {
      padding-top: 20px;
      font-size: 22px;
      color: #666;
      width: auto;
      height: auto;
      border: none;
      small {
        display: block;
        font-size: 15px;
        color: #999;
      }
    }
  }
  .extra {
    background-color: #333;
  }
  .slogan {
    height: 178px;
    line-height: 58px;
    padding: 60px 100px;
    border-bottom: 1px solid #434343;
    display: flex;
    justify-content: space-between;
    a {
      height: 58px;
      line-height: 58px;
      color: #fff;
      font-size: 28px;
      i {
        font-size: 50px;
        vertical-align: middle;
        margin-right: 10px;
        font-weight: 100;
      }
      span {
        vertical-align: middle;
        text-shadow: 0 0 1px #333;
      }
    }
  }
  .copyright {
    height: 170px;
    padding-top: 40px;
    text-align: center;
    color: #999;
    font-size: 15px;
    p {
      line-height: 1;
      margin-bottom: 20px;
    }
    a {
      color: #999;
      line-height: 1;
      padding: 0 10px;
      border-right: 1px solid #999;
      &:last-child {
        border-right: none;
      }
    }
  }
}
</style>

4.4 头部导航动态数据

定义一个常量数据和后台保持一致(约定好9大分类),这样不请求后台就能展示一级分类,不至于白屏。

定义九个分类常量数据 src/api/constants.js

// 顶级分类
export const topCategory = [
  '居家',
  '美食',
  '服饰',
  '母婴',
  '个护',
  '严选',
  '数码',
  '运动',
  '杂货'
]

定义API函数 src/api/category.js

// 定义首页需要的接口函数
import request from '@/utils/request'

/**
 * 获取首页头部分类数据
 */
export const findAllCategory = () => {
    return request.get('/api/xhr/globalinfo/queryTop.json')
}

跨域配置

const path = require('path')
module.exports = {
    //跨域请求
    devServer: {
      proxy: {
        '/api': {
          target: 'http://you.163.com',//网易新闻接口
          ws: true,
          changeOrigin: true,
          pathRewrite: {//重写路径
            '^/api': ''
          }
        },
        '/foo': {
          target: 'http://localhost:3333',//本地接口
          ws: true,
          changeOrigin: true,
          pathRewrite: {//重写路径
            '^/foo': ''
          }
        },
      },
    }
}

vuex在category模块,来存储分类数据,提供修改和获取的函数。

import { topCategory } from '../../api/constants';
import { findAllCategory } from '../../api/category';

export default {
    namespaced: true,
    state() {
        return {
            list: topCategory.map(ele => ({ name: ele })),
        }
    },
    //加载数据成功后需要修改list所以需要mutations函数
    mutations: {
        setList(state, headCategory) {
            state.list = headCategory
        },
    },
    // 需要向后台加载数据,所以需要actions函数获取数据
    actions:{
        async getList({commit}){
            const res = await findAllCategory();
            commit('setList',res.data.data.cateList)
        }
    }
}

导航组件数据获取

<template>
  <ul class="app-header-nav">
    <li><RouterLink to="/">首页</RouterLink></li>
     <li v-for="item in list" :key='item.id'  @mouseenter="show(item)" @mouseleave="hide(item)">
        <RouterLink  @click="change(item)" :to='"/category/"+item.id'>{{item.name}}</RouterLink>
        <div class="layer" :class="{active:item.open}">
          <ul>
            <li v-for="ele in item.subCateGroupList" :key="ele.id">
              <RouterLink :to='"/category/sub/"+ele.id' @click="change(item)">
                <img :src="ele.categoryList[0].bannerUrl" alt="">
                <p>{{ele.name}}</p>
              </RouterLink>
            </li>
          </ul>
        </div>
    </li>
   
  </ul>
</template>

<script>
import {useStore} from 'vuex';
import {computed} from 'vue';

export default {
  name: "AppHeaderNav",
  setup(){
    const store = useStore();
    const list = computed(()=>{
      return store.state.category.list
    })

    //点击事件
    const change=(item)=>{
      item.open=false
    }
    //显示
    const show=(item)=>{
      item.open= true
    }
    //隐藏
    const hide=(item)=>{
      item.open=false
    }
    return {list,change,show,hide}
  }
};
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值