天天看點

uni-app學習記錄——2.uni-app搭建一個網上商城

文章目錄

  • ​​1.建立項目 & 清理結構 & 配置基本外觀​​
  • ​​2.完成底部tabbar的配置​​
  • ​​3.擷取輪播圖資料​​
  • ​​4.實作輪播圖的結構和資料渲染​​
  • ​​5.實作菜單導航結構​​
  • ​​5.1 引入字型圖示初始化樣式​​
  • ​​5.2 完成菜單導航基本結構​​
  • ​​5.3 菜單導航樣式​​
  • ​​6.實作推薦商品清單​​
  • ​​6.1 定義基本結構​​
  • ​​6.2 美化樣式​​
  • ​​6.3 擷取資料​​
  • ​​6.4 渲染資料​​
  • ​​7.完成超市頁面​​
  • ​​7.1 改造導航菜單​​
  • ​​7.2 建立超市頁面​​
  • ​​7.3 封裝商品清單元件​​
  • ​​7.4 渲染商品清單​​
  • ​​7.5 實作上拉加載更多​​
  • ​​7.6 實作下拉重新整理​​
  • ​​8.關于我們​​
  • ​​9.實作社群圖檔​​
  • ​​10.實作資訊清單​​
  • ​​10.1 實作清單項的結構和樣式​​
  • ​​10.2 封裝為元件​​
  • ​​10.3 在新聞頁面導入并使用​​
  • ​​10.4 點選清單進入詳情​​
  • ​​11.實作資訊詳情​​
  • ​​11.1 實作基本結構​​
  • ​​11.2 擷取詳情的資料​​
  • ​​11.3 實作詳情的渲染​​
  • ​​12.實作商品詳情頁​​
  • ​​12.1 商品清單注冊點選事件​​
  • ​​12.2 父元件綁定自定義事件進行跳轉​​
  • ​​12.3 建立商品詳情頁​​
  • ​​12.4 擷取詳情輪播圖資料​​
  • ​​12.5 渲染輪播圖​​
  • ​​12.6 擷取商品資訊​​
  • ​​12.7 完成商品資訊結構和渲染​​

1.建立項目 & 清理結構 & 配置基本外觀

  • 利用HBuilder X建立基本項目結構
  • 運作項目
  • 整理基本項目結構,并修改視窗外觀
"globalStyle": {
  "navigationBarTextStyle": "white",
  "navigationBarTitleText": "黑馬商城",
  "navigationBarBackgroundColor": "#1989fa",
  "backgroundColor": "#F8F8F8"
}      

2.完成底部tabbar的配置

  • 建立tabbar對應的四個頁面和圖示準備好
  • 将頁面路徑配置到pages.json中的pages數組中
"pages": [ //pages數組中第一項表示應用啟動頁,參考:https://uniapp.dcloud.io/collocation/pages
    {
      "path": "pages/index/index"
    },
    {
      "path": "pages/member/member"
    },
    {
      "path": "pages/cart/cart"
    },
    {
      "path": "pages/search/search"
    }
  ]      
  • 配置tabbar
{
  "tabBar": {
    "list": [
      {
        "pagePath":"pages/index/index",
        "text":"首頁",
        "iconPath":"static/icon/home.png",
        "selectedIconPath":"static/icon/home-active.png"
      },
      {
        "pagePath":"pages/member/member",
        "text":"會員",
        "iconPath":"static/icon/member.png",
        "selectedIconPath":"static/icon/member-active.png"
      },
      {
        "pagePath":"pages/cart/cart",
        "text":"購物車",
        "iconPath":"static/icon/cart.png",
        "selectedIconPath":"static/icon/cart-active.png"
      },
      {
        "pagePath":"pages/search/search",
        "text":"搜尋",
        "iconPath":"static/icon/search.png",
        "selectedIconPath":"static/icon/search-active.png"
      }
    ]
    
  }
}      

3.擷取輪播圖資料

  • 封裝uni.request請求,并挂在到全局
  • 建立util》api.js
// 封裝get請求
const baseUrl = "http://localhost:8082"
export const myRequest = (options)=>{
  return new Promise((resolve,reject)=>{
    uni.request({
      method: options.method,
      data: options.data,
      url: baseUrl+options.url,
      success(res) {
        if(res.data.status !== 0) {
          return uni.showToast({
            title: '擷取資料失敗'
          })
        }
        resolve(res)
      },
      fail(err) {
        uni.showToast({
          title: '擷取資料失敗'
        })
        reject(err)
      }
    })
  })
}      
  • 在main.js中導入并挂載到全局
import { myRequest } from './util/api.js'
Vue.prototype.$myRequest =      
  • 擷取輪播圖的資料
  • 定義擷取輪播圖的方法
methods: {
  async getSwipers () {
    const res = await this.$myRequest({
      method: 'GET',
      url: '/api/getlunbo'
    })
    this.swipers = res.data.message
  }
}      
  • 在onLoad中調用該方法
this.getSwipers()      

4.實作輪播圖的結構和資料渲染

  • 定義輪播圖的基本結構
<swiper class="swiper" indicator-dots :autoplay="true" :interval="2000" circular>
  <swiper-item v-for="item in swipers" :key="item.id">
    <image :src="item.img"></image>
  </swiper-item>
</swiper>      
  • 樣式,在工具中安裝scss
<style lang="scss">
  .home{
    swiper{
      height: 380rpx;
      image{
        width: 750rpx;
        height: 380rpx;
      }
    }
  }      

5.實作菜單導航結構

5.1 引入字型圖示初始化樣式

<style>
  @font-face {font-family: "iconfont";
    src: url('~@/static/fonts/iconfont.eot?t=1576335469449'); /* IE9 */
    src: url('~@/static/fonts/iconfont.eot?t=1576335469449#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAVMAAsAAAAAChwAAAT/AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDKAqHQIYhATYCJAMUCwwABCAFhG0HUBurCFGUTk6f7EeBu6eIlFFajBY208XLlGHx/6/hiYfvx76d+2xFJLlUn75pp4tCoyQ8NgiJUJjuJfzNpSrpXIDoeDbs3GjyH7Lfv+zTy1mok+GyEhYAW8AKaPvz/6eeG1QvDUo6SQW8bE4KYTDSMRj1R/5x7/TP88Dmo7Jc/misYXOelwWYYEBjbGxrAQ7KEvQW8SwuJBO4nkCvRQ21q/PbB5hXQLdAvDU6gHmbRQnhhG598xlb1lEvsu70PvEBfFU/H/+hF1IkNYO+149nMRz+6v7/fwrv4JAqI6T5uXCbRMYWUIhnX8+tKT22ZUrvJ3PaCdCNryR+Sb2RfRPT+c9kbdF0s788siIRDWj6GXkWL/ySEsVkfsmyftoYKiIZsiQfJ+Y2ll7MgdgDiE/AMF+CumLWsCSpdFXpjsNkefoatW8WSY8xapRhreWm1a9vWvVEM6edaQdPapImTzTLLG4BwEBG/HJsK4bVEKkStJbxbUYy3othvO2ofJA7jBARcUZ4illDuEL29TB2C/3AGWj4WUfGYbG25LTICaEk1jWBR8KWC0bqQJ+EjJYmOnvisiHzqtifvZ08X7NYzBaJWAJBglDIRIi3Fd/C3cbZjqEKvkh9Qmx2SKCgMAhD15VHVkCQMCWOP72YnLB0euHUpROzJ/PEYiR6wxK8ShC+ZsryVibGlbIzorOjqRKnhwyOKTIlMRoPSLgMlYvInDIKdwsQ8K2YbO2PReRsyxzZvrK0dWxUYUrIE2sPj8+sHNw6tUVhj0AgslvelUfhDnNG4k0YwgedbyX/ovPRL8SnqwOt/atMII/RGGMacyXGJOaq+MtGYDFMOL1Hk8OSJdfqARNMZkPmnDVh5DP0bjDpx6XAB6RO0JkqM4F0fNSNZMKXB20QqI//n+swdzCvnv1/JszOzMEszPsskD8RZtrarNB14gGhubjWlduokVnWD9e9PyCQd1jtvPjStKTGs6VZFT/xjhhW0hpkG6PoC0wW8iGUrPK9prFY4AM+9GF8APhKfIvr5tct+IoAxU/eE3ILa4yrDxTgUfkrG0lPTtshU4pGtXT9UJqywWkDhzyi/5ka15D+WlPn1Gd+QYF7s0j3dXTuS0oStZLum6on86NOwIbPcydIP3+STiDFaYk1Z6WFLPt7b7M6EhMA+Gr+qtDilfia4mPFr0p8JZUS973QHulzYJxsPjJ6xdeW7Wd75WHHrZsGDXaUb1hacCuQVmrOkt1DjdgTxSeY3EcWDqCzRLxB9PmH2DNplYhzhCDbNLfzY7dKy1jb/dqNFfBTXbWg8vhWsH1JP9IN0VQmIcif4isHay1vtVDzNIiyxeirbpZ0JKEXg3QAAqN+8jFMLN9E6DZhQtJlAbJuS2ght6DqcwRNt1Potelicp8xbEqUHmz4IBCGfUIy6DtkwyZoIb+hmvQLzXAQoddNbM3ZZyWKFk+YAqEYwxGayJZKsMuiVnxH2ucBW+Uq94m4MkHstjrO5AWVxHkMqPq6J6JQsS3wnGxGeW7RsU0pklYi4rbbbeV3plZkC1h0iZGAIDEUGkFGxCopubpYdL3/DtG8XIBDSn4knxBWMbWjrpZODPRCU8YqWZfGlT6tRwjFOynMKqBz6iI5xizk/FulSES0JCkizrY2q6Tialrl64ppLD0VysKcNVLkKFGjae8S40w5K14OB+WS9lKjkR/YgsrZsRnZzAAA') format('woff2'),
    url('~@/static/fonts/iconfont.woff?t=1576335469449') format('woff'),
    url('~@/static/fonts/iconfont.ttf?t=1576335469449') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
    url('~@/static/fonts/iconfont.svg?t=1576335469449#iconfont') format('svg'); /* iOS 4.1- */
  }
  
  .iconfont {
    font-family: "iconfont" !important;
    font-size: 16px;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
  
  .icon-shipin:before {
    content: "\f0024";
  }
  
  .icon-tupian:before {
    content: "\e650";
  }
  
  .icon-guanyuwomen:before {
    content: "\e608";
  }
  
  .icon-ziyuan:before {
    content: "\e60d";
  }      

5.2 完成菜單導航基本結構

<view class="nav">
      <view class="item">
        <view class="iconfont icon-ziyuan"></view>
        <text>黑馬超市</text>
      </view>
      <view class="item">
        <view class="iconfont icon-tupian"></view>
        <text>聯系我們</text>
      </view>
      <view class="item">
        <view class="iconfont icon-guanyuwomen"></view>
        <text>社群圖檔</text>
      </view>
      <view class="item">
        <view class="iconfont icon-shipin"></view>
        <text>視訊專區</text>
      </view>
    </view>      

5.3 菜單導航樣式

.nav{
  display: flex;
  align-items: center;
  .item{
    width: 25%;
    text-align: center;
    view{
      background: $shop-color;
      line-height: 120rpx;
      width: 120rpx;
      height: 120rpx;
      border-radius: 90px;
      margin:10px auto;
    }
    text{
      font-size: 15px;
    }
  }
  .iconfont{
    font-size: 25px;
    color: #fff;
    height: 50px;
  }
  .icon-tupian{
    font-size: 20px;
  }
}      

6.實作推薦商品清單

6.1 定義基本結構

<view class="hot_goods">
  <view class="tit">推薦商品</view>
  <!-- 一般用法 -->
  <view class="goods_list">
    <view class="goods_item">
      <image></image>
      <view class="price">
        <text>1299</text>
        <text>12990</text>
      </view>
      <view class="name">華為(HUAWEI)榮耀6Plus 16G雙4G版</view>
    </view>
  </view>
</view>      

6.2 美化樣式

.hot_goods {
  background: #eee;
  .tit{
    border-top: 2px solid #eee;
    border-bottom: 2px solid #eee;
    margin-top: 20px;
    margin-bottom: 3px;
    color: $shop-color;
    height: 50px;
    line-height: 50px;
    text-align: center;
    letter-spacing: 20px;
    background: #fff;
  }
  .goods_list {
    display: flex;
    padding: 0 15rpx;
    justify-content: space-between;
    overflow: hidden;
    flex-wrap: wrap;
    .goods_item {
      width: 355rpx;
      margin-bottom: 15rpx;
      background: #fff;
      padding: 10px;
      box-sizing: border-box;
      image{
        height: 150px;
        width: auto;
        mix-width:160px;
        margin: 10px auto;
      }
      .price{
        font-size: 18px;
        color: red;
        padding: 8px 0;
        text:nth-child(2){
          color: #ccc;
          text-decoration: line-through;
          margin-left: 10px;
          font-size: 13px;
        }
      }
      .name {
        font-size: 14px;

      }
    }
  }
}      

6.3 擷取資料

  • 定義擷取資料的方法
// 擷取推薦商品
async getGoods () {
  const res = await this.$myRequest({
    url: '/api/getgoods?pageindex=1'
  })
  this.goods = res.data.message
}      
  • 在onLoad生命周期中調用該方法
this.getGoods()      

6.4 渲染資料

  • 通過v-for渲染資料
<view class="hot_goods">
  <view class="tit">推薦商品</view>
  <!-- 一般用法 -->
  <view class="goods_list">
    <view class="goods_item" v-for="item in goods" :key="item.id">
      <image :src="item.img_url"></image>
      <view class="price">
        <text>{{item.sell_price}}</text>
        <text>{{item.market_price}}</text>
      </view>
      <view class="name">{{item.title}}</view>
    </view>
  </view>
</view>      

7.完成超市頁面

7.1 改造導航菜單

  • 定義資料
navs: [
  {
    icons: "iconfont icon-ziyuan",
    title: "黑馬超市",
    path: "/pages/goods/list"
  },
  {
    icons: "iconfont icon-tupian",
    title: "社群圖檔",
    path: "/pages/pics/pics"
  },
  {
    icons: "iconfont icon-guanyuwomen",
    title: "聯系我們",
    path: "/pages/contact/contact"
  },
  {
    icons: "iconfont icon-shipin",
    title: "學習視訊",
    path: "/pages/videos/videos"
  }
]      
  • 渲染資料
<view class="nav">
  <view class="item" v-for="(item,index) in navs" :key="index">
    <view :class="item.icons"></view>
    <text>{{item.title}}</text>
  </view>
</view>      
  • 給導航菜單注冊點選事件
<view class="goods_item" v-for="item in goods" :key="item.id">      
  • 定義跳轉的方法
goNavigator (url) {
  uni.navigateTo({
    url
  })
}      

7.2 建立超市頁面

  • 建立頁面,goods>list.vue
  • 将頁面路勁配置到pages檔案中,修改标題

7.3 封裝商品清單元件

  • 在components下面建立goods>list.vue
<template>
  <view class="goods_list">
    <view class="goods_item" v-for="item in goods" :key="item.id">
      <image :src="item.img_url"></image>
      <view class="price">
        <text>{{item.sell_price}}</text>
        <text>{{item.market_price}}</text>
      </view>
      <view class="name">{{item.title}}</view>
    </view>
  </view>
</template>

<script>export default {
    props:{
      goods:Array
    }
  }</script>

<style lang="scss">.goods_list {
    display: flex;
    padding: 0 15rpx;
    justify-content: space-between;
    overflow: hidden;
    flex-wrap: wrap;
    .goods_item {
      width: 355rpx;
      margin-bottom: 15rpx;
      background: #fff;
      padding: 10px;
      box-sizing: border-box;
      image{
        height: 150px;
        width: 150px;
        display: block;
        margin: 10px auto;
      }
      .price{
        font-size: 18px;
        color: red;
        padding: 8px 0;
        text:nth-child(2){
          color: #ccc;
          text-decoration: line-through;
          margin-left: 10px;
          font-size: 13px;
        }
      }
      .name {
        font-size: 14px;
        
      }
    }
  }</style>      
  • 在首頁引入該元件
import goodsList from "../../components/goods-list/index.vue"

components: {
  "goods-list":goodsList
}      
  • 使用元件并将資料傳遞到元件内部
<goods-list :goods="goods"></goods-list>      

7.4 渲染商品清單

  • 定義擷取商品清單資料的方法并調用
<script>
  export default {
    data () {
      return {
        goods: []
      }
    },
    methods: {
      async getGoods () {
        const res = await this.$myRequest({
          url: '/api/getgoods?pageindex=1'
        })
        this.goods = res.data.message
      },
    },
    
    onLoad () {
        this.getGoods()
    }
  }
</script>      
  • 引入商品元件并使用
<template>
  <view class="goods_list">
    <goods-list :goods="goods"></goods-list>
  </view>
</template>
<script>
  import goodsList from "../../components/goods-list/index.vue"
  export default {
    components: {
      "goods-list": goodsList
    }
  }
</script>
      

7.5 實作上拉加載更多

  • 通過onReachBottom來監聽觸底
onReachBottom () {
  this.pageindex++
  this.getGoods()
}      
  • 修改給goods指派
this.goods = [...this.goods,...res.data.message]      
  • 動态顯示底線
  • 通過onReachBottom監聽是否還有更多
if(this.pageindex*10>this.goods.length) return this.flag = true      
  • 通過v-if控制底線
<view class="over_line" v-if="flag">----------我是有底線的----------</view>      

7.6 實作下拉重新整理

  • 通過onPullDownRefresh進行下拉重新整理的操作
onPullDownRefresh() {
  this.goods = []
  this.pageindex = 1
  this.flag = false 
  setTimeout(()=>{
    this.getGoods(()=>{
      uni.stopPullDownRefresh()
    })
  },1000)
}      

8.關于我們

<template>
  <view class="contact">
    <image class="img" src="https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3252521864,872614242&fm=26&gp=0.jpg"></image>
    <view class="info">
      <view @click="phone">聯系電話:123-456-789(點選撥打)</view>
      <view>聯系位址:CSDN-赈川</view>
    </view>
    <map class="map" v-bind:longitude="longitude" v-bind:latitude="latitude" v-bind:markers="markers"></map>
    聯系我們
  </view>
</template>

<script>export default {
    data() {
      return {
        longitude : 108.910649,
        latitude: 34.158268,
        markers:[
          {
            longitude : 108.910649,
            latitude: 34.158268,
            iconPath : '../../static/logo.png'
          }
        ]
      }
    },
    methods: {
      phone(){
        uni.makePhoneCall({
          phoneNumber: '123-456-789'
        })
      }
    }
  }</script>

<style lang="scss">.contact{
    .img{
      width: 750rpx;
      height: 320rpx;
    }
    .info{
      padding: 10rpx 20rpx;
      font-size: 30rpx;
      view{
        line-height: 80rpx;
        border-bottom: 1px solid #eee;
      }
    }
    .map{
      width: 750rpx;
      height: 750rpx;
    }
  }</style>      

9.實作社群圖檔

<template>
  <view class="pics">
    <scroll-view class="left" scroll-y="true">
      <view @click="leftClickHandle(index,item.id)" v-bind:class="active==index?'active':''" v-bind="active" v-for="(item,index) in cates" v-bind:key="item.id">
        {{item.title}}
      </view>
    </scroll-view>
    <scroll-view class="right" scroll-y="true">
      <view class="item" v-for="item in secondData" v-bind:key="item.id">
        <image @click="previewImg(item.img_url)" v-bind:src="item.img_url"></image>
        <text>{{item.title}}</text>
      </view>
      <text v-if="secondData.length === 0">暫無資料</text>
    </scroll-view>
  </view>
</template>

<script>export default {
    data() {
      return {
        cates : [],
        active : 0,
        secondData : []
      }
    },
    methods: {
      async getPicsCate(){
        const res = await this.$myRequest({
          url: ' /api/getimgcategory'
        })
        this.cates = res.data.message
        this.leftClickHandle(0,this.cates[0].id)
      },
      async leftClickHandle(index,id){
        this.active = index;
        // 擷取右側渲染的資料
        const res = await this.$myRequest({
          url : '/api/getimages/' + id 
        })
        this.secondData = res.data.message;
      },
      previewImg(current){
        const urls = this.secondData.map(item => {
          return item.img_url;
        })
        uni.previewImage({
          current,
          urls
        })
      }
    },
    onLoad(){
      this.getPicsCate()
    }
  }</script>

<style lang="scss">// 适配微信小程式
  page{
    height: 100%;
  }
  .pics{
    height: 100%;
    display: flex;
    .left{
      width: 200rpx;
      height: 100%;
      border-right: 1px solid #eee;
      view{
        height: 60px;
        line-height: 60px;
        color: #333;
        text-align: center;
        font-size: 30rpx;
        border-top: 1px solid #eee;
      }
      .active{
        background: $shop-color;
        color: #fff;
      }
    }
    .right{
      height: 100%;
      width: 520rpx;
      margin: 10rpx auto;
      .item{
        image{
          width: 520rpx;
          height: 520rpx;
          border-radius: 5px;
        }
        text{
          font-size: 30rpx;
          line-height: 60rpx;
        }
      }
    }
    
  }</style>      

10.實作資訊清單

10.1 實作清單項的結構和樣式

結構

<view class="news_item">
  <image src="../../static/logo.png"></image>
  <view class="content">
    <view class="tit">1季度多家房企利潤跌幅超50% 去庫存促銷戰打響</view>
    <view class="info">
      <text>發表時間:2019-12-23</text>
      <text>浏覽:1次</text>
    </view>
  </view>
</view>      

樣式

.news{
  .news_item{
    display: flex;
    padding: 5px 10px;
    border-bottom: 3px solid $shop-color;
    image{
      width: 300rpx;
      height: 150rpx;
    }
    .content {
      padding: 5px 10px;
      position: relative;
      .tit{
        font-size: 30rpx;
      }
      .info{
        font-size: 26rpx;
        position: absolute;
        left: 10px;
        bottom: 5px;
        text:nth-child(2){
          margin-left: 20px;
        }
      }
    }
  }
}      

10.2 封裝為元件

<template>
  <view>
    <view class="news_item" v-for="item in data" :key="item.id">
      <image :src="item.img_url"></image>
      <view class="content">
        <view class="tit">{{item.title}}</view>
        <view class="info">
          <text>發表時間:{{item.add_time | formatDate}}</text>
          <text>浏覽:{{item.click+123}}次</text>
        </view>
      </view>
    </view>
  </view>
</template>

<script>export default {
    props: ['data'],
    filters:{
      formatDate(data){
        const date = new Date(data)
        console.log(date)
        const day = date.getMonth().toString().padStart(2,'0')+'-'+date.getDay().toString().padStart(2,'0')
        return date.getFullYear()+'-'+day
      }  
    }
  }</script>

<style lang="scss">.news_item{
    display: flex;
    padding: 5px 10px;
    border-bottom: 1rpx solid $shop-color;
    image{
      max-width: 200rpx;
      min-width: 200rpx;
      height: 150rpx;
    }
    .content {
      padding: 5px 10px;
      position: relative;
      .tit{
        font-size: 30rpx;
      }
      .info{
        font-size: 26rpx;
        position: absolute;
        left: 10px;
        bottom: 5px;
        text:nth-child(2){
          margin-left: 20px;
        }
      }
    }
  }</style>      

10.3 在新聞頁面導入并使用

<template>
  <view class="news">
    <new-item :data="newsList"></new-item>
  </view>
</template>
<script>import newItem from '../../components/new-item/new-item.vue'
  export default {
    data() {
      return {
        newsList: []
      }
    },
    methods: {
      async getNewsList () {
        const res = await this.$myRequest({
          url:'/api/getnewslist'
        })
        this.newsList = res.data.message
      }
    },
    onLoad () {
      this.getNewsList()
    },
    components: {
      "new-item":newItem
    }
  }</script>

<style lang="scss">
</style>      

10.4 點選清單進入詳情

  • 點選子元件清單項通過this.$emit觸發父元件的方法
navigatorTo (item) {
  this.$emit('clickItem',item)
}      
  • 父元件通過注冊clickItem事件及事件函數實作跳轉操作
<template>
  <view class="news">
    <new-item :data="newsList" @clickItem="goDetail"></new-item>
  </view>
</template>
<script>export default {
    methods: {
      goDetail (data) {
        console.log(data)
        uni.navigateTo({
          url: '/pages/news-detail/news-detail'
        })
      }
    }
  }</script>      
  • 建立/pages/news-detail/news-detail頁面

11.實作資訊詳情

11.1 實作基本結構

<template>
  <view class="news_detail">
    <view class="news_title">
      标題
    </view>
    <view class="info">
      <text>發表時間:</text>
      <text>浏覽:</text>
    </view>
    <view class="content">
      
    </view>
  </view>
</template>

<script>export default {
    data() {
      return {
        
      }
    },
    methods: {
      
    }
  }</script>

<style lang="scss">.news_detail {
  padding: 15rpx;
  .news_title{
    text-align: center;
    font-size: 32rpx;
  }
  .info{
    font-size: 28rpx;
    display: flex;
    justify-content: space-between;
  }
}</style>      

11.2 擷取詳情的資料

methods: {
  async getNewsDetail(id){
    const res = await this.$myRequest({
      url: '/api/getnew/'+id
    })
    console.log(res)
    this.newsDetail = res.data.message[0]
  }
},

  onLoad (options){
    this.getNewsDetail(options.id)
  }      

11.3 實作詳情的渲染

<view class="news_title">
  {{newsDetail.title}}
    </view>
<view class="info">
  <text>發表時間:{{newsDetail.add_time | formatDate}}</text>
<text>浏覽:{{newsDetail.click}}</text>
</view>
<view class="content">
  <rich-text :nodes="newsDetail.content"></rich-text>
</view>      

12.實作商品詳情頁

12.1 商品清單注冊點選事件

<template>
  <view class="goods_list">
    <view @click="itemClick(item)" class="goods_item" v-for="item in goods" :key="item.id">
    </view>
  </view>
</template>
<script>
  export default {
    props:{
      goods:Array
    },
    methods: {
      itemClick(item) {
        this.$emit('itemClick',item)
      }
    }
  }
</script>      

12.2 父元件綁定自定義事件進行跳轉

<goods-list @itemClick="godetail" :goods="goods"></goods-list>      

12.3 建立商品詳情頁

12.4 擷取詳情輪播圖資料

methods: {
  async getDetail(){
    const res = await this.$myRequest({
      url:'/api/getthumimages/'+this.id
    })
    console.log(res)
  }
},
onLoad(options){
    this.id = options.id
    this.getDetail()
}      

12.5 渲染輪播圖

<swiper indicator-dots>
  <swiper-item v-for="item in swipers" :key="item.src">
    <image :src="item.src"></image>
  </swiper-item>
</swiper>
<style lang="scss">.goods_detail{
  swiper{
    height: 700rpx;
    image{
      width: 100%;
      height: 100%;
    }
  }
}</style>      

12.6 擷取商品資訊

methods: {
  async getDetailInfo () {
    const res = await this.$myRequest({
      url:'/api/goods/getinfo/'+this.id
    })
    this.info = res.data.message[0]
  }
},
onLoad(options){
    this.id = options.id
    this.getDetailInfo()
}      

12.7 完成商品資訊結構和渲染