前言
实战已经开始了!上一篇文章将首页中的店铺列表数据动态化了,也是为了详情页而做准备的,从本章节起就要开始做详情页了,但是随着页面路由越来越多,在做详情页之前,需要将路由变为异步加载。其次首页列表和详情页顶部部分是一样的,所以将其组件化。
详情页路由 - 异步路由
🌀 既然要做详情页了,就得先创建页面,在配置路由。
- 在views目录下新建shop文件夹 - Shop.vue文件
- 内容可以是默认的空模板
- 在router配置文件中,引入shop页面,并配置shop路由。
import Shop from '../views/shop/Shop' 复制代码
{ path: '/shop', name: 'Shop', component: Shop } 复制代码
😫 目前路由配置中已经有四个路由配置了,在加载首页的时候,也会将其他暂时不需要加载的页面配置一起加载进来,这样其实是没必要的,所以需要将路由配置成异步的。
😲 以前的文章中,一起学习过异步路由配置,下面就简单回顾一下
👉 首先将首页和登录页配置异步路由,看看页面加载时的效果
{ path: '/', name: 'Home', component: () => import(/* webpackChunkName: "home" */ '../views/home/Home') },{ path: '/login', name: 'Login', component: () => import(/* webpackChunkName: "login" */ '../views/login/Login'), beforeEnter (to, from, next) { const { isLogin } = localStorage isLogin ? next({ name: 'Home' }) : next() } } 复制代码
- component中是一个回调函数,通过import实现异步加载路由。
- webpackChunkName是异步加载路由时,打包的js名称。
- 通过页面加载可以看出,进入首页时会单独加载首页配置路由,进入登录页时也会单独加载登录页的路由,但是进入注册页的时候,不会单独加载注册页的路由,那是因为注册页的路由在另外一个公共js里面加载出来的。
🔆 根据上面的方式,将所有路由配置都改成异步路由。
import { createRouter, createWebHashHistory } from 'vue-router' const routes = [ { path: '/', name: 'Home', component: () => import(/* webpackChunkName: "home" */ '../views/home/Home') }, { path: '/shop', name: 'Shop', component: () => import(/* webpackChunkName: "shop" */ '../views/shop/Shop') }, { path: '/login', name: 'Login', component: () => import(/* webpackChunkName: "login" */ '../views/login/Login'), beforeEnter (to, from, next) { const { isLogin } = localStorage isLogin ? next({ name: 'Home' }) : next() } }, { path: '/register', name: 'Register', component: () => import(/* webpackChunkName: "register" */ '../views/register/Register'), beforeEnter (to, from, next) { const { isLogin } = localStorage isLogin ? next({ name: 'Home' }) : next() } } ] 复制代码
- 因为是异步加载路由,所以顶部不需要引入路由文件了,只需要在component中异步引入路由即可。
拆分列表组件
🌀 通过对比稿图,我们发现列表页和详情页的部分内容是一致的,可以将其拆分出来单独维护。
👉 在components文件夹下新建shopItem组件
👉 将首页中循环列表里面的内容和样式复制到shopItem组件中
<template> <div class="shop"> <img :src="item.imgUrl" class="shop__img"> <div class="shop__content"> <div class="shop__content__title">{{item.name}}</div> <div class="shop__content__tags"> <span class="shop__content__tag">月售:{{item.sales}}</span> <span class="shop__content__tag">起送:{{item.expressLimit}}</span> <span class="shop__content__tag">基础运费:{{item.expressPrice}}</span> </div> <p class="shop__content__highlight">{{item.slogan}}</p> </div> </div> </template> 复制代码
<style lang="scss" scoped> @import "../style/viriables.scss"; .shop { display: flex; padding-top: 0.12rem; &__img { margin-right: 0.16rem; width: 0.56rem; height: 0.56rem; } &__content { flex: 1; padding-bottom: 0.12rem; border-bottom: 1px solid #f1f1f1; &__title { line-height: 0.22rem; font-size: 0.16rem; color: $content-font-color; } &__tags { margin-top: 0.08rem; line-height: 0.18rem; font-size: 0.13rem; color: $content-font-color; } &__tag { margin-right: 0.16rem; } &__highlight { margin: 0.08rem 0 0 0; line-height: 0.18rem; font-size: 0.13rem; color: #e93b3b; } } } </style> 复制代码
- 需要注意的是公共样式也要引入进来。
- 为了符合当前页面的内容,所以将样式名称统一成一样的前缀。
👉 首页引入子组件
import ShopItem from '../../components/shopItem' 复制代码
👉 通过components定义组件
components: { ShopItem } 复制代码
👉 循环展示子组件,并传递循环内容给子组件
<ShopItem v-for="item in nearbyList" :key="item.id" :item="item" /> 复制代码
- 循环的时候还是使用id作为key值,并将循环的item通过v-bind指令传递给子组件。
👉 子组件接收传递过来的值并渲染出来
<script> export default { name: 'ShopItem', props: ['item'] } </script> 复制代码
详情页引入组件
🌀 通过详情页稿图可以看出只有顶部一块内容是子组件,所以不需要进行循环,我们可以先定义静态数据渲染出来,后续在改成动态数据。
👉 详情页引入组件
import ShopItem from '../../components/shopItem' 复制代码
👉 通过components定义组件
components: { ShopItem } 复制代码
👉 模板中使用子组件
<template> <div class="wrapper"> <ShopItem :item="item" /> </div> </template> 复制代码
👉 setup函数中定义静态数据渲染
setup () { const item = { id: 1, name: '沃尔玛', imgUrl: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-a8a16cef-f2b9-4644-b216-3b95bcb12602/e9e2929d-f491-489d-8fa5-bd6223e67b06.png', sales: 1000, expressLimit: 0, expressPrice: 5, slogan: 'VIP尊享满89元减4元运费券(每月3张)' } return { item } } 复制代码
- 详情页中渲染子组件之后发现这里有一条线,是在首页用来分割列表的,详情页中是不需要的。
⭕️ 我们可以使用基础篇章中用过的动态样式来渲染这条线的显隐。
动态渲染样式
👉 在shopItem组件中接收一个参数:hideBorder
props: ['item', 'hideBorder'] 复制代码
👉 将content中的border样式注释,并新增一个下级样式
&--bordered { border-bottom: 1px solid #f1f1f1; } 复制代码
- 表示只有标识了bordered的样式名才显示底部边框线。
👉 将content样式通过动态绑定样式来显示
<div :class="{'shop__content': true, 'shop__content--bordered': hideBorder ? false : true}"></div> 复制代码
- shop__content是原始样式名,所以直接设置为true。
- shop__content--bordered是用来显示底部边框线的,通过hideBorder来判断显示隐藏。
👉 由于详情页不需要显示边框线,所以在详情页中给子组件传递hideBorder
<template> <div class="wrapper"> <ShopItem :item="item" :hideBorder="true" /> </div> </template> 复制代码
👆 详情页的border就隐藏了。
👆 首页的列表就会多出一个bordered样式名用来显示边框线了。
总结
本篇文章主要是将路由配置中引用组件的时候变成异步引入的方式,并且将首页和详情页中公共的组件拆分出来复用,通过动态样式传递来显隐部分样式内容。