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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/552976.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络 TCP/IP体系 物理层

一. TCP/IP体系 物理层 1.1 物理层的基本概念 物理层作为TCP/IP网络模型的最低层&#xff0c;负责直接与传输介质交互&#xff0c;实现比特流的传输。 要完成物理层的主要任务&#xff0c;需要确定以下特性&#xff1a; 机械特性&#xff1a;物理层的机械特性主要涉及网络…

CSS3 max/min-content及fit-content、fill-available值的详解

c3中对width的值多了几个值&#xff1a;fill-available, max-content, min-content, 以及fit-content。 1.width:fill-available 我们在页面中扔一个没有其他样式的<div>元素&#xff0c;则&#xff0c;此时&#xff0c;该<div>元素的width表现就是fill-availabl…

SAP打印输出设置

SAP打印输入有很多方式&#xff0c;适合不同的应用场景。 一.打印输出总体概览图 二.前台打印 这个是比较常见的&#xff0c;前端打印的出现减轻了管理员的工作量&#xff0c;用户可以选择自己电脑上的打印机输出&#xff0c;不需要所有打印机都在SAP平台中进行配置&#xff0…

web 学习第六次课程

文章目录 定位 定位 <body><div style"height:100px;width:100px;border:#F00 1px solid;"></div><div style"height:100px;width:100px;border: #00F 1px solid;"></div> </body><body><div style"pos…

Go 语言中的 GIF 图像处理完全指南:`image/gif`的技术与实践

Go 语言中的 GIF 图像处理完全指南&#xff1a;image/gif的技术与实践 概述安装与基础设置导入 image/gif 包初步配置示例&#xff1a;设置一个简单的 GIF 编码环境 读取与解码 GIF 图像读取 GIF 文件解析 GIF 数据 创建与编码 GIF 图像创建 GIF 图像编码 GIF 图像 处理 GIF 动…

【深度学习】wandb模型训练可视化工具使用方法

【深度学习】wandb模型训练可视化工具使用方法 wandb简介功能介绍登陆注册以及API keysproject和runsproject和runs的关系 wandb的配置实验跟踪版本管理Case可视化分析可视化自动调参&#xff08;wandb.sweep&#xff09;配置wandb.sweep1.配置 sweep_config2.初始化 sweep con…

学习STM32第十五天

SPI外设 一、简介 STM32F4XX内部集成硬件SPI收发电路&#xff0c;可以由硬件自动执行时钟生成、数据收发等功能&#xff0c;减轻CPU负担&#xff0c;可配置8位/16位数据帧&#xff0c;高位&#xff08;最常用&#xff09;/低位先行&#xff0c;三组SPI接口&#xff0c;支持DMA…

网站怎么实现HTTPS访问?

网站实现HTTPS的过程主要分为以下几个步骤&#xff1a; 1. 申请SSL证书&#xff1a; - 根据网站需求选择合适的SSL证书类型&#xff0c;DV证书只需验证域名所有权&#xff0c;适用于个人网站或小型项目&#xff1b;OV和EV证书需验证企业身份信息&#xff0c;适用于对信任度要求…

使用GAN做图像超分——SRGAN,ESRGAN

在GAN出现之前&#xff0c;使用的更多是MSE&#xff0c;PSNR,SSIM来衡量图像相似度&#xff0c;同时也使用他们作为损失函数。 但是这些引以为傲的指标&#xff0c;有时候也不是那么靠谱&#xff1a; MSE对于大的误差更敏感&#xff0c;所以结果就是会倾向于收敛到期望附近&am…

spring05:代理模式 和 AOP

spring05&#xff1a;代理模式 和 AOP 文章目录 spring05&#xff1a;代理模式 和 AOP前言一、静态代理模式&#xff08;代理类直接写好&#xff09;1. &#xff08;房东租房子 的案例&#xff09; 二、动态代理模式&#xff08;代理类是动态生成的&#xff09;1. &#xff08;…

动态代理,XML,Dom4j

文章目录 动态代理概述特点代码实现实现的关键步骤优点 XML概述作用编写第一个XML文件组成声明元素(标签、标记)属性注释转义字符[实体字符字符区(了解) 约束DTD约束Schema约束名称空间 Dom4jXML解析解析方式和解析器解析方式解析器Snipaste_2024-04-17_21-22-44.png<br /&g…

竞赛 基于LSTM的天气预测 - 时间序列预测

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 机器学习大数据分析项目 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/po…

【机器学习300问】74、如何理解深度学习中L2正则化技术?

深度学习过程中&#xff0c;若模型出现了过拟合问题体现为高方差。有两种解决方法&#xff1a; 增加训练样本的数量采用正则化技术 增加训练样本的数量是一种非常可靠的方法&#xff0c;但有时候你没办法获得足够多的训练数据或者获取数据的成本很高&#xff0c;这时候正则化技…

pajamas 1 daydream.sequence-template

0. 老实交代&#xff0c;最近对于python&#xff0c;非常之感冒 热天气常驻之后&#xff0c;各种毛病就来了&#xff1a;蚊子很彪悍&#xff0c;牙齿不舒服&#xff0c;肠胃那更是一坨 … 虽然不久前&#xff0c;荷包大残&#xff0c;但是关注到 mac mini 之后&#xff0c;就…

项目7-音乐播放器5+注册账号

1.前端代码 MAPPER Insert("insert into user(username,password) values (#{username},#{password}) ")Integer insertUserInfo(String username,String password); Service public Result insertUserInfo(String username, String oldpassword,String newpasswo…

MAC电脑M1安装OpenCV

最近在学习研究OpenCV&#xff0c;奈何只有mac电脑。安装OpenCV感觉还是挺麻烦的&#xff0c;所以记录一下&#xff0c;难免以后会忘记。 安装OpenCV我参考的帖子 https://www.bilibili.com/read/cv23613225/ 一、首先安装Anaconda 目前已安装不做赘述 二、启动命令窗口 方…

SpringBoot搭建环境

创建项目向导 用idea向导建SpringBoot项目&#xff1a;菜单 > File > New > Project… 选择向导&#xff1a; 默认向导 https://start.spring.io 建议用 https://start.aliyun.com 配置项目信息 Group : 组织名 Artifact : 项目名 Version : 版本号 name : 与Artifa…

【在线OJ系统】自定义注解实现分布式ID无感自增

实现思路 首先自定义参数注解&#xff0c;然后根据AOP思想&#xff0c;找到该注解作用的切点&#xff0c;也就是mapper层对于mapper层的接口在执行前都会执行该aop操作&#xff1a;获取到对于的方法对象&#xff0c;根据方法对象获取参数列表&#xff0c;根据参数列表判断某个…

Hbase的简单学习一

一 Hbase的搭建与安装 1.1 安装 1.准备好文件&#xff0c;上传到Linux上 2.解压文件 tar zxvf hbase-2.2.7-bin.tar.gz -C ../ ../是解压到的路径 1.2 配置文件 1.配置环境变量 去etc/profile目录下 export HBASE_HOME/usr/local/soft/hbase-2.2.7 export PATH$PATH:$H…

Midjourney 实现角色一致性的新方法

AI 绘画的奇妙之处&#xff0c;实乃令人叹为观止&#xff01;就像大千世界中&#xff0c;寻不见两片完全相同的树叶一般&#xff0c;AI 绘画亦复如是。同一提示之词&#xff0c;竟能催生出千变万化的图像&#xff0c;使得AI所绘之作&#xff0c;宛如自然之物般独特&#xff0c;…
最新文章