第 4-2 課:前後端交互之首頁實現
目錄
- 開篇
- 基礎篇
- 前端篇
1 邏輯處理
client
新建 models/IndexModel.js
import { CloudRequest } from '../utils/cloud-request.js'
class IndexModel extends CloudRequest {
/**
* 獲取首頁輪播
* @param {*} callBack
*/
getBanner(callBack) {
this.request({
url: "getBanner",
success: res => {
callBack(res)
}
})
}
/**
* 獲取主題
* @param {*} callBack
*/
getTheme(callBack){
this.request({
url: "getTheme",
success: res => {
callBack(res)
}
})
}
/**
* 獲取最新商品
* @param {*} callBack
*/
getProductNew(callBack){
this.request({
url: "getProductNew",
success: res => {
callBack(res)
}
})
}
}
export { IndexModel }
大家看到這個有沒有有點熟悉又是不熟悉,在其他裏面我們可能一個 js 裏面有很多方法,我們需要每一個方法導出才能使用,然後 require 引入直接使用,類是通過導出類名,import 引入實例化後我們才能使用。希望大家在實際的過程中不要搞混了。 callBack 是回調函數,將數據拋給上層,類是 ES6特性,如果不是很熟悉可以回頭看下。
2 前臺數據處理
回到我們 pages/index/index.js
,下面我貼出實現的代碼,直接在方法上面註釋說明
// pages/index/index.js
// 引入我們需要的類
import { IndexModel } from "../../models/IndexModel.js"
// 使用錢需要實例化才能使用
let index = new IndexModel()
Page({
/**
* 頁面的初始數據
*/
data: {
indicatorDots: true, //是否顯示面板指示點
autoplay: true, //自動輪播
interval: 3000, // 自動切換時間間隔
duration: 1000, // 滑動動畫時長
circular: true,//是否採用銜接滑動
themes:[
{ theme_icon: 'images/[email protected]', theme_name: '新品糖果', theme_type:1},
{ theme_icon: 'images/[email protected]', theme_name: '精品果乾', theme_type: 2 },
{ theme_icon: 'images/[email protected]', theme_name: '美味堅果', theme_type: 3 },
{ theme_icon: 'images/[email protected]', theme_name: '優質推薦', theme_type: 4 },
],
banners:[],
products:[]
},
/**
* 生命週期函數--監聽頁面加載
*/
onLoad: function (options) {
// _下劃線開頭 代表私有方法 我們將所有的進來加載數據存放在_init方法
this._init()
},
// 頁面初始化數據
_init:function(){
// 輪播圖 在頭部我們實例化 複製給index 在這裏我們直接通過實例名稱調用裏面的方法,res=>{} 取出我們回調函數的值,取出我們想要的結果,在setData
index.getBanner(res => {
this.setData({
banners : res.result.data.data
})
})
// 主題
index.getTheme(res =>{
this.setData({
themes : res.result.data.data
})
})
// 最新商品
index.getProductNew(res=>{
this.setData({
products : res.result.data.data
})
})
},
/**
* 主題跳轉
*/
themeNavigation: function (event) {
let theme_type = indexModel.getDataSet(event, "theme_type")
wx.navigateTo({
url: '../theme/theme?theme_type=' + theme_type,
})
},
// 跳轉商品詳情
productDetails: function (e) {
this._navProductDetail(e.detail.productId)
},
productBanner: function (event) {
let product_id = indexModel.getDataSet(event, "productid")
this._navProductDetail(product_id)
},
// 跳轉詳情
_navProductDetail: function (product_id) {
wx.navigateTo({
url: '/pages/product/product?product_id=' + product_id,
})
}
})
在這裏我沒有一個的編寫對接主要是我們在前端編寫的時候靜態頁面已經完成,後臺也完成並測試了,只剩下的數據交互了,取出數據渲染數據。可能篇幅就比較大,在這裏我更多的時候採用註釋的形式,在
cloud-request
封裝的 getDataSet 只要繼承了cloud-request
我們就能直接使用,不需要再打印出來複製屬性取值。大家在直接開發的過程中私有方法,一定記得使用_
下劃線開頭,這樣在我們實際開發中也能養成良好的開發習慣。
pages/index/index.wxml
<!--pages/index/index.wxml-->
<view class='container'>
<!--1、輪播圖 -->
<swiper class='swiper-container' indicator-dots="{{indicatorDots}}" indicator-active-color='#fff'
autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" circular="{{circular}}">
<block wx:for="{{banners}}" wx:key="">
<swiper-item class='swiper-item' data-productId='{{item.product_id}}' bind:tap="productBanner">
<image class='swiper-img' src="{{item.image}}" mode='scaleToFill' />
</swiper-item>
</block>
</swiper>
<!-- 2、主題欄 -->
<view class='theme-container' >
<block wx:for="{{themes}}" wx:key="index" >
<view class='theme-box' data-themeType="{{item.theme_type}}" bind:tap='themeNavigation'>
<view class='theme-icon'>
<image src='{{item.theme_icon}}'></image>
</view>
<text>{{item.theme_name}}</text>
</view>
</block>
</view>
<!-- 分割線 -->
<view class='dividing-line'></view>
<!-- 3、最新上線 -->
<view class='products-latest-container'>
<title-bar-comp title='最新上線'></title-bar-comp>
<block wx:for="{{products}}" wx:key="key">
<product-cloumn-comp product="{{item}}" bind:productDetails="productDetails"></product-cloumn-comp>
</block>
</view>
</view>
<product-cloumn-comp product="{{item}}" bind:productDetails="productDetails"></product-cloumn-comp>`
product="{{item}}" product:組件屬性對應,{{item}} :參數傳遞
bind:productDetails="productDetails"
bind:productDetails:中的productDetails取自triggerEvent(組件事件通信),
後面的productDetails:表示wxml的對應的js中方法
triggerEvent如果還不瞭解的,這裏是官方組件間通信與事件組件間通信
components/behaviors/product-behavior.js
商品信息 Behavior ,在這裏我們之前的新增 properties
和 methods
module.exports = Behavior({
behaviors: [],
properties: {
product: { // 屬性名
type: Object,
value: '', // 屬性初始值(可選),如果未指定則會根據類型選擇一個
observer: function (product) {
}
}
},
methods: {
// 商品詳情
productDetails: function () {
// 返回
this.triggerEvent("productDetails", {
productId: this.data.product._id
}, {})
}
}
})
components/product-column/index.wxml
<!--components/product-column/index.wxml-->
<!-- 商品展示左右分隔 product-left product-left product-right -->
<view class='container'>
<!-- 商品展示左邊 -->
<view class='product-left'>
<view class='product-img' >
<image src="{{product.product_img}}"></image>
</view>
</view>
<!-- 商品展示右邊 -->
<view class='product-right'>
<!-- 商品基本信息上部分 -->
<view ><text class='product-title'>{{product.product_name}}</text></view>
<!-- 商品基本信息下部分 -->
<view class='product-content' >
<!-- 市場價 -->
<view class='market-price-container'>
<text>市場價:</text>
<text>¥</text>
<text>{{product.product_price}}</text>
</view>
<!-- 優惠價 -->
<view class='discount-price-container'>
<view class='discount-price-left'>
<text class='discount-price-desc' >優惠價:</text>
<text class='discount-price-symbol' >¥</text>
<text class='discount-price' >{{product.product_sell_price}}</text>
</view>
<view class='discount-price-right' bind:tap='productDetails'>
<button class='go'>立即購買</button>
</view>
</view>
</view>
</view>
</view>
樣式在之前靜態頁面已經完成
- 類的繼承和方法的實現,callback 回調返回結果,引用後實例化之後調用方法。
- 頁面也組件的通信,頁面參數傳遞組件 properties 需要對應,組件事件通過 triggerEvent 通信。
3 代碼分解
3.1 靜態數據分析
themes: [
{ theme_icon: 'images/[email protected]', theme_name: '新品糖果', theme_type: 1 },
{ theme_icon: 'images/[email protected]', theme_name: '精品果乾', theme_type: 2 },
{ theme_icon: 'images/[email protected]', theme_name: '美味堅果', theme_type: 3 },
{ theme_icon: 'images/[email protected]', theme_name: '優質推薦', theme_type: 4 },
]
因爲在很多的時候,比如菜單和分類都是前臺靜態固定的,在這裏我先靜態在動態獲取,這樣我後臺修改數據就不需要前臺重新打包上傳,也能在頁面加載的時候緩解頁面的渲染時間。
3.2 初始化 _init
頁面加載初始化數據處理使用 _init 方法,提取之後我們的 onLoad 就看起來簡潔。
// 頁面初始化數據
_init:function(){
// 輪播圖 在頭部我們實例化 複製給index 在這裏我們直接通過實例名稱調用裏面的方法,res=>{} 取出我們回調函數的值,取出我們想要的結果,在setData
index.getBanner(res => {
this.setData({
banners : res.result.data.data
})
})
// 主題
index.getTheme(res =>{
this.setData({
themes : res.result.data.data
})
})
// 最新商品
index.getProductNew(res=>{
this.setData({
products : res.result.data.data
})
})
}
首頁的輪播、主題、最新商品都是通過後臺讀取,上面的代碼裏面 res 則是我們在 model 中 callback 回調的值,然後在通過小程序的 this.setData
將返回的結果賦值,在頁面上通過則組要 {{}}
渲染數據。
3.3 頁面跳轉
首頁一般爲展示關鍵性數據,作爲軟件的一個引導,進一步的操作我們都需要跳轉,頁面與頁面的跳轉我們需要參數,在小程序中獲取參數的值如下:
data-自定義名 = 值 // data 爲微信小程序提供的一種賦值的格式
data-themeType="{{item.theme_type}}"
通過綁定進行方法的調用, event 獲取頁面 data 的值
//wxml
bind:tap='themeNavigation'
// themeNavigation => themeNavigation 對應
// js
themeNavigation:fucntion(event){
}
使用 cloud-request
的 getDataSet 方法獲取事件綁定的值。
/**
* 主題跳轉
*/
themeNavigation: function (event) {
let theme_type = indexModel.getDataSet(event, "theme_type")
wx.navigateTo({
url: '../theme/theme?theme_type=' + theme_type,
})
}
項目地址
在搭建項目前,根據自己需要下載本系列文章的源代碼