vue 一个简单的项目 之三 详情页面 step1

本文详细介绍如何在Vue项目中实现动态路由跳转至详情页面,并进行Banner布局设计。通过修改Recommend.vue组件,利用router-link实现点击跳转,同时保持样式一致。在Detail组件中引入Banner组件,完成美观的响应式布局。

第三个页面 详情页面。本篇主要是来做详情页面的动态路由和banner 布局。

首先,git 上新建分支 detail-banner,pull 下来,在新分支上工作。

我们希望,在首页点击下面 热销推荐中每一项,会进入详情页。

首页,使用的是Recommend.vue 组件。我们该一下Recommend.vue 的代码,给它的li 包裹一个路由跳转的标签,如下。

<template>
  <div>
    <div class="title">热销推荐</div>
    <ul>
      <router-link to='/detail'>
        <li class="item border-bottom" v-for="item of list" :key="item.id">
          <img class="item-img" :src='item.imgUrl' />
          <div class="item-info">
            <p class="item-title">{{item.title}}</p>
            <p class="item-desc">{{item.desc}}</p>
            <button class="item-button">查看详情</button>
          </div>
        </li>
      </router-link>
    </ul>
  </div>
</template>

上面这么做,功能上是可以的。但是li 中的字体样式会变化。

我们可以写css,还原这种变化,但是有一种更好的解决方法,如下。

我们把li 直接改为router-link 标签,再加上tag = "li" 。这样在浏览器渲染的时候,不会把router-link 渲染称 <a> 标签,而是会渲染成li 标签。

<template>
  <div>
    <div class="title">热销推荐</div>
    <ul>
      <router-link
        tag="li"
        class="item border-bottom"
        v-for="item of list"
        :key="item.id"
        :to="'/detail/' + item.id"
      >
        <img class="item-img" :src='item.imgUrl' />
        <div class="item-info">
          <p class="item-title">{{item.title}}</p>
          <p class="item-desc">{{item.desc}}</p>
          <button class="item-button">查看详情</button>
        </div>
      </router-link>
    </ul>
  </div>
</template>

好啦。Recommend.vue 页面就做这些修改啦。

下面我们去路由配置文件 src/router/index.js 页面,添加路由。

注意,由于我们上面进入的路由是带参数的(item.id),因此,我们配置的路由,配置动态路由。

index.js 如下。path 为 ‘/detail/:id’ 表示,这个路径,前面必须是 /detail/ 后面是参数,参数则保存在 变量id 中。

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/pages/home/Home.vue'
import City from '@/pages/city/City.vue'
import Detail from '@/pages/detail/Detail.vue'
Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    }, {
      path: '/city',
      name: 'City',
      component: City
    }, {
      path: '/detail/:id',
      name: 'Detail',
      component: Detail
    }
  ]
})

好的,然后去建detail 的组件。

先在src/pages 里建一个文件夹 detail,然后在文件夹里面,建一个文件 Detail.vue.

初始化 Detail.vue 如下。

<template>
  <div>hello</div>
</template>

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

<style lang="stylus" scoped>

</style>

下面,我们来写详情页面的banner 布局。

我们pages/detail 下建一个目录 components, 在这个目录下建一个文件 Banner.vue。如下。

<template>
  <div>hello</div>
</template>

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

<style lang="stylus" scoped>

</style>

在 Detail.vue 中引入Banner.vue ,如下。

<template>
  <div>
    <detail-banner></detail-banner>
  </div>
</template>

<script>
import DetailBanner from './components/Banner'
export default {
  name: 'Detail',
  components: {
    DetailBanner
  }
}
</script>

<style lang="stylus" scoped>

</style>

我们写一下,Banner.vue 里的代码。

<template>
  <div class="banner">
    <img class="banner-img" src="https://dimg07.c-ctrip.com/images/w30k0o000000esrxi8010.jpg_Z_800_600.jpg">
    <div class="banner-info">
      <div class="banner-title">
        孔雀蓝天空
      </div>
      <div class="banner-number">
        <span class="iconfont banner-icon">&#xe632;</span>
        100
      </div>
    </div>
  </div>
</template>

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

<style lang="stylus" scoped>
  .banner
    position: relative
    overflow: hidden
    height: 0
    padding-bottom: 55%
    .banner-img
      width: 100%
    .banner-info
      display: flex
      position: absolute
      left: 0
      right: 0
      bottom: 0
      color: #fff
      line-height: .6rem
      background-image: linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.8))
      .banner-title
        flex: 1
        font-size: .32rem
        padding: 0 .2rem
      .banner-number
        height: .32rem
        line-height: .32rem
        margin-top: .14rem
        padding: 0 .4rem
        border-radius: .2rem
        background: rgba(0,0,0,.8)
        font-size: .24rem
        .banner-icon
          font-size: .24rem
</style>

好啦,这块儿布局完成。

<think>好的,用户现在想在Vue2项目中实现页面之间的流程切换,也就是通过路由导航来实现。用户之前问了关于如何手动引入GSAP的问题,现在转向了Vue Router的使用。我需要结合用户提供的引用内容,特别是引用[1]和引用[2]中的信息,来给出解决方案。 首先,用户提到了“页面流程切换”,这通常指的是在单页应用(SPA)中不同组件或页面之间的导航,而不会重新加载整个页面Vue Router正是Vue.js官方推荐的路由管理器,适合实现这个需求。 根据引用[2],Vue Router的基本使用包括安装、配置路由规则、使用router-link和router-view。用户需要先安装vue-router@3版本,因为Vue2对应的是3.x版本的vue-router。安装后,需要在项目中应用插件,并配置路由规则,定义路径和对应的组件。 然后,用户可能需要动态路由,这在引用[3]中提到了vue3的实现,但用户是在Vue2项目中。不过动态路由的概念在Vue2中也是存在的,可以通过路由参数的匹配来实现,比如在路由配置中使用带参数的路由路径,如`path: '/user/:id'`,这样可以在不同用户页面之间切换。 导航守卫也是关键部分,引用[1]提到了导航守卫的使用。导航守卫允许在路由跳转前、跳转后或跳转过程中执行一些逻辑,比如权限验证或页面跟踪。用户可能需要使用全局前置守卫(beforeEach)来检查用户是否有权限访问某个页面,或者在进入某个路由前获取必要的数据。 另外,用户提到了声明式和编程式导航。声明式导航是通过<router-link>组件,而编程式导航则是通过Vue Router提供的API,比如router.push()或router.replace()。这在引用[1]中已经说明,用户需要根据场景选择合适的方式。 需要注意,用户可能在配置路由时遇到问题,比如路由不生效,或者组件未正确加载。这时候需要检查路由配置是否正确,组件是否导入,以及是否正确挂载到Vue实例上。此外,动态路由的添加和删除可能需要用到addRoutes方法,不过Vue2中的动态路由添加方式与Vue3不同,需要特别注意。 用户还可能关心如何传递参数,比如通过params或query,以及如何在组件中获取这些参数。例如,使用$route.params.id来获取动态路由参数,或者使用$route.query来获取查询字符串参数。 最后,结合用户之前的GSAP手动引入问题,可能需要考虑在路由切换时添加动画效果,比如使用Vue的过渡组件结合GSAP来实现页面切换的动画,这会提升用户体验。不过用户当前的问题主要集中在路由导航的实现,所以需要先确保路由配置正确,再考虑添加动画。</think>### Vue2实现页面流程切换的完整方案 #### 一、基础路由配置(核心实现) 1. **安装依赖**(需使用vue-router@3) 若无法使用npm,可直接引入CDN: ```html <!-- 在public/index.html中追加 --> <script src="https://unpkg.com/vue-router@3.6.5/dist/vue-router.js"></script> ``` 2. **路由配置文件** 创建`src/router/index.js`: ```javascript const routes = [ { path: '/order', component: () => import('../views/OrderFlow.vue'), children: [ { path: 'step1', component: () => import('../components/Step1.vue') }, { path: 'step2', component: () => import('../components/Step2.vue') }, { path: 'step3', component: () => import('../components/Step3.vue') } ] }, { path: '*', redirect: '/order/step1' } // 默认重定向 ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router ``` 3. **主入口注入路由** 修改`main.js`: ```javascript import Vue from 'vue' import App from './App.vue' import router from './router' new Vue({ router, render: h => h(App) }).$mount('#app') ``` #### 二、流程切换实现方式 1. **声明式导航**(适合固定路径) 在`.vue`组件中使用: ```vue <template> <router-link :to="{ name: 'Step2' }" class="nav-btn" tag="button"> 下一步 </router-link> </template> ``` 2. **编程式导航**(动态逻辑控制) 在方法中调用: ```javascript methods: { handleNextStep() { if(this.formValid) { this.$router.push({ path: '/order/step2', query: { trackingId: this.trackingCode } }) } } } ``` 3. **动态路径参数**(带状态传递) 路由配置: ```javascript { path: '/payment/:orderId', component: PaymentView, props: true // 启用props接收参数 } ``` 跳转时: ```javascript this.$router.push(`/payment/${this.currentOrder.id}`) ``` #### 三、流程控制进阶技巧 1. **导航守卫控制流程** ```javascript router.beforeEach((to, from, next) => { if (to.path === '/order/step2' && !localStorage.getItem('step1Data')) { next('/order/step1') // 强制返回第一步 } else { next() } }) ``` 2. **路由元信息验证** 路由配置: ```javascript { path: '/checkout', component: Checkout, meta: { requiresAuth: true } } ``` 守卫处理: ```javascript router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { if (!auth.isLogin) next('/login') else next() } else { next() } }) ``` #### 四、可视化流程状态维护 ```vue <template> <div class="process-steps"> <div v-for="(step, index) in steps" :key="index" :class="['step', { 'active': currentStep === index }]"> {{ step.title }} </div> </div> </template> <script> export default { computed: { currentStep() { const pathMap = { '/step1': 0, '/step2': 1, '/step3': 2 } return pathMap[this.$route.path] } } } </script> ``` #### 五、常见问题解决方案 | 问题现象 | 解决方案 | |---------|----------| | 页面刷新后路由丢失 | 使用`mode: 'history'`时需配置服务器重定向规则 | | 路由参数未更新 | 使用`watch: { '$route'(to) { ... } }`监听变化 | | 组件复用不刷新 | 在`<router-view>`添加`:key="$route.fullPath"` | ### 最佳实践建议 1. **路由懒加载**提升性能: ```javascript component: () => import(/* webpackChunkName: "order" */ './views/Order.vue') ``` 2. **统一错误处理**: ```javascript router.onError((error) => { console.error('路由错误:', error) router.push('/error') }) ``` 3. **滚动行为控制**: ```javascript const router = new VueRouter({ scrollBehavior(to, from, savedPosition) { return { x: 0, y: 0 } } }) ``` ### 流程切换动效示例 ```vue <template> <transition name="fade-slide" mode="out-in" @enter="handleEnter" @leave="handleLeave"> <router-view/> </transition> </template> <script> import { gsap } from 'gsap' export default { methods: { handleEnter(el, done) { gsap.from(el, { duration: 0.5, x: 300, opacity: 0, onComplete: done }) }, handleLeave(el, done) { gsap.to(el, { duration: 0.3, x: -300, opacity: 0, onComplete: done }) } } } </script> ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值