一级片大奶子_色又黄又爽18禁免费视频_热久久久久久久_久久久精品一区二区_日韩av不卡在线播放_精品国内自产拍在线观看视频

商城系統 注冊

商城小程序簡易開發教程(mpvue+koa+mongodb)

2018-07-27|HiShop
導讀:隨著移動互聯網時代的發展,許多傳統電商都有了自己的小程序商城,那么對于新手來說如何簡單開發一款小程序商城系統呢。...

隨著移動互聯網時代的發展,許多傳統電商都有了自己的小程序商城,那么對于新手來說如何簡單開發一款小程序商城系統呢。

商城小程序簡易開發教程(mpvue+koa+mongodb)

技術棧

前端: 微信小程序、mpvue

后端:koa

數據庫:mongodb 數據庫可視化工具:Robo3T

商城小程序開跑

一個基本的商城小程序,包含了前端的首頁、分類、購物車、我的(訂單)四個tab頁,后端的數據定義、分類、和存取。各有其色,我在下面就相應介紹一些主要功能、對比原生小程序和vue.js所踩到的坑還有后端數據庫的功能應用。 想了解或者有何問題都可以去 作品源碼 中了解哦。

成果分享

一、前臺頁面及功能

 

1. 談組件封裝

舉個栗子說,首頁由三部分組成:頭部輪播推薦+中間橫向滑動推薦+縱向滾動商品list。這三部分,幾乎是所有商城類app必需的功能了。頭部的輪播推薦、中間的橫向滑動式推薦的封裝,我們都知道,諸如此類的功能組件,在各app上基本都少不了,最初學vue最先有所體會的,便是組件代碼復用性高的特點,在進行一些組件復用遷移至別的組件或頁面時,可能都不需要改動代碼或者改動少量代碼就可以直接使用,可以說是相當方便了,對于mpvue組件內仍然支持原生小程序的swiper與scroll,兩者兼容后,對于熟知小程序和vue的開發者,這項功能可以很高效率地完成。

最后主頁面文件就是由一個個組件組成,可讀性很強了,對于初學者來說,模塊封裝的思想是首先就得具備的了。

<template>
  <div class="container" @click="clickHandle('test click', $event)">
    <div class="swiperList">
      <swiper :text="motto" :swiperList="swiperlist"></swiper>
    </div>
    <div class="navTab">
      <div class="recTab">
        <text>  ——  為你推薦  ——</text>
    </div>
    </div>
    <scroll></scroll>
    <div class="hot">
      <span> —— 熱門商品 ——</span>
    </div>
    <hot :v-text="motto"></hot>
    <div class="fixed-img">
      <img :src="fixImg"    </div>
  </div>
</template>
復制代碼

不過關于組件封裝與組合的問題,由于最近有研究vue性能優化和用戶體驗的一些知識點,考慮了一個比較嚴肅的問題:

先看一下常見的vue寫法:在html里放一個app組件,app組件里又引用了其他的子組件,形成一棵以app為根節點的組件樹:

<body>
    <app></app> 
</body>
復制代碼

而這種做法就引發了性能問題,要初始化一個父組件,必然需要先初始化它的子組件,而子組件又有它自己的子組件。那么要初始化根標簽,就需要從底層開始冒泡,將頁面所有組件都初始化完。所以我們的頁面會在所有組件都初始化完才開始顯示。

這個結果顯然不是我們要的,用戶每次點開頁面,還要面對一陣子的空白和響應,因為頁面啟動后不止要響應初始化頁面的組件,還有包含在app里的其他組件,這樣嚴重拖慢了頁面打開的速度。

更好的結果是頁面可以從上到下按順序流式渲染,這樣可能總體時間增長了,但首屏時間縮減,在用戶看來,頁面打開速度就更快了。網上一些辦法大同小異,各有優缺點,所以...本人也在瘋狂試驗中,靜待好消息。

**2.Class、Style的綁定 **

在不同父組件中引用同一子組件時,但是各自需要接收綁定的動態樣式去呈現不同的樣式,在綁定css style樣式這一關上,踩了個大坑:mpvue居然不支持用object的形式傳style,起先處于樣式一直上不去的抓狂當中,網上對于mpvue這方面的細節也少之又少,后來查找了許多地方,發現class和style的綁定都是不支持classObj和styleObj形式,就嘗試用了字符串,果然...改代碼改到懷疑人生,結果你告訴我人生起步就是錯誤,怎能不心痛?...

解決:

<template>
<div class="swiper-list">
    <d-swiper :swiperList="swiperlist" :styleObject="styleobject"></d-swiper>
</div>
</template>
<script>
    data() {
        return {
            styleobject:'width:100%;height:750rpx;position:absolute;top:0;z-index:3'
        }
    }
</script>
復制代碼

3. “v-for嵌套”陷阱

在做vue項目的時候難免會用到循環,需要用到index索引值,但是v-for在嵌套時index沒辦法重復用,內循環與外循環不能共用一個index。

<swiper-item v-for="(items,index) in swiperList" :key="index">
    <div v-for="item in items" class="swiper-info" :key="item.id" @click="choose" >
        <image :src="item.url"  class="swiper-image" :style="styleObject"/>
    </div>
</swiper-item>
復制代碼
 

而給內循環再加上另一個索引,便沒有報錯:

<swiper-item v-for="(items,index) in swiperList" :key="index">
    <div v-for="(item,i) in items" class="swiper-info" :key="i" @click="choose" >
        <image :src="item.url"  class="swiper-image" :style="styleObject"/>
    </div>
</swiper-item>
復制代碼

4.this指向問題與箭頭函數的應用

這是vue文檔里的原話:All lifecycle hooks are called with their 'this' context pointing to the Vue instance invoking it.

意思是:在Vue所有的生命周期鉤子方法(如created,mounted, updated以及destroyed)里使用this,this指向調用它的Vue實例,即(new Vue)。 mpvue里同理。 我們都知道,生命周期函數中的this都是指向Vue實例的,因此我們就可以訪問數據,對屬性和方法進行運算。

props:{
    goods:Array
},
mounted: function(options){
    let category = [
      {id: 0, name: '全部'},
      {id: 1, name: 'JAVA'},
      {id: 2, name: 'C++'},
      {id: 3, name: 'PHP'},
      {id: 4, name: 'VUE'},
      {id: 5, name: 'CSS'},
      {id: 6, name: 'HTML'},
      {id: 7, name: 'JavaScript'}
    ]
    this.categories = category
    this.getGoodsList(0)
  },
methods: {
    getGoodsList(categoryId){
      console.log(categoryId);
      if(categoryId == 0){
        categoryId = ''
      }
      wx.request({
        url: 'http://localhost:3030/shop/goods/list',
        data: {
          categoryId: categoryId
        },
        method: 'POST', 
        success: res => {
          console.log(res);
          this.goods = res.data.data;
        }
      })
    },
}
復制代碼

普通函數this指向這個函數運行的上下文環境,也就是調用它的上下文,所以在這里,對于生命周期函數用普通函數還是箭頭函數其實并沒有影響,因為它的定義環境與運行環境是同一個,所以同樣能取到vue實例中數據、屬性和方法。 箭頭函數中,this指向的是定義它的最外層代碼塊,()=>{} 等價于 function(){}.bind(this);所以this當然指向的是vue實例。起初并沒有考慮到this指向的問題,在wx.request({})中success用了普通函數,結果一直報錯“goods is not defined”,用了箭頭函數才解決,起初普通函數的this指向 getGoodsList()的上下文環境,所以一直沒辦法取到值。

5.onLoad與onShow

在進行首頁點擊商品跳轉到詳情頁時,onLoad()無法獲取更新數據。

首先雖然onLoad: function (options) 這個是可以接受到值的,但是這個只是加載一次,不是我想要的效果,我需要在本頁面(不關閉的情況下)到另外一個頁面在跳轉進來,接收到對應商品的數據。

所以需要將代碼放在onshow內部, 在每次頁面加載的時候都會進行當前狀態的查詢,查詢對應數據的子對象,更新渲染到詳情頁上。

onShow: function(options){
    // console.log(this.styleobject)
      // console.log(options)
    wx.getStorage({
      key: 'shopCarInfo',
      success: (res) =>{
        // success
        console.log(`initshopCarInfo:${res.data}`)
        this.shopCarInfo = res.data;
        this.shopNum = res.data.shopNum
      }
    })
    wx.request({
      url: 'http://localhost:3030/shop/goods/detail',//請求detail數據表的數據
      method: 'POST',
      data: {
        id: options.id
      },
      success: res =>{
        // console.log(res);
        const dataInfo = res.data.data.basicInfo;
        this.saveShopCar = dataInfo;
        this.goodsDetail.name = dataInfo.name;
        this.goodsDetail.minPrice = dataInfo.minPrice;
        this.goodsDetail.goodsDescribe = dataInfo.characteristic;

        let goodsLabel = this.goodsLabel
        goodsLabel = res.data.data;
        // console.log(goodsLabel);
        this.selectSizePrice = dataInfo.minPrice;
        this.goodsLabel.pic = dataInfo.pic;
        this.goodsLabel.name = dataInfo.name;
        this.buyNumMax = dataInfo.stores;
        this.buyNumMin = (dataInfo.stores > 0) ? 1 : 0;
      }
    })
  }
復制代碼

了解小程序onLoad與onShow生命周期函數:

onLoad:生命周期函數–監聽小程序初始化,當小程序初始化完成時,會觸發 onLoadh(全局只觸發一次)。

onShow:生命周期函數–監聽小程序顯示,當小程序啟動,或從后臺進入前臺顯示,會觸發 onShow。

二、后臺數據庫及數據存取

1.架設 HTTP 服務

在全局配置文件中: 1).引入koa并實例化

const Koa = require('koa');
const app = new Koa()
復制代碼

2).app.listen(端口號):創建并返回 HTTP 服務器,將給定的參數傳遞給Server#listen()。

const Koa = require('koa');//引入koa框架
const app = new Koa();
app.listen(3000);
這里的app.listen()方法只是以下方法的語法糖:

const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
復制代碼

這樣基本的配置完畢,我們就可以用“http://localhost3030+請求地址參數”獲取到數據庫的值了。

2.Koa-router路由中間件

koa-router 是常用的 koa 的路由庫。

如果依靠ctx.request.url去手動處理路由,將會寫很多處理代碼,這時候就需要對應的路由的中間件對路由進行控制,這里介紹一個比較好用的路由中間件koa-router。

以路由切換催動界面切換,”數據化”界面。

3.建立對象模型

在構建函數庫之前,先來聊聊對象的建模。

Mongoose是在node.js異步環境下對mongodb進行便捷操作的對象模型工具。該npm包封裝了操作mongodb的方法。

Mongoose有兩個特點:

1、通過關系型數據庫的思想來設計非關系型數

2、基于mongodb驅動,簡化操作

 

const mongoose = require('mongoose')

const db = mongoose.createConnection('mongodb://localhost/shop') //建立與shop數據庫的連接(shop是我本地數據庫名)
復制代碼

本地數據庫shop中建了分別“地址管理”、“商品詳情”、“訂單詳情”、“商品列表”、“用戶列表”五個數據表:

 

Schema界面定義數據模型:

Schema用于定義數據庫的結構。類似創建表時的數據定義(不僅僅可以定義文檔的結構和屬性,還可以定義文檔的實例方法、靜態模型方法、復合索引等),每個Schema會映射到mongodb中的一個collection,但是Schema不具備操作數據庫的能力。

數據表跟對象的映射,同時具有檢查效果,檢查每組數據是否滿足模型中定義的條件 同時,每個對象映射成一個數據報表,就可用該對象進行保存操作,等同操作數據表,而非mysql命令行般繁瑣的操作

以“商品列表”數據表為例:

// 模型通過Schema界面定義。
var Schema = mongoose.Schema;

const listSchema = new Schema({
  barCode: String,
  categoryId: Number,
  characteristic: String,
  commission: Number,
  commissionType: Number,
  dateAdd: String,
  dateStart: String,
  id: Schema.Types.ObjectId,
  logisticsId: Number,
  minPrice: Number,
  minScore: Number,
  name: String,
  numberFav: Number,
  numberGoodReputation: Number,
  numberOrders: Number,
  originalPrice: Number,
  paixu: Number,
  pic: String,
  pingtuan: Boolean,
  pingtuanPrice: Number,
  propertyIds: String,
  recommendStatus: Number,
  recommendStatusStr: String,
  shopId: Number,
  status: Number,
  statusStr: String,
  stores: Number,
  userId: Number,
  videoId: String,
  views: Number,
  weight: Number,
})

復制代碼

定義了數據表中需要的數據項的類型,數據表傳入數據后會一一對應:

 

4.koa-router“路由庫”

const Router = require('koa-router')()//引入koa-router
const router = new Router();// 創建 router 實例對象
//注冊路由
router.post('/shop/goods/list', async (ctx, next) => {
  const params = ctx.request.body
  //以‘listSchema’的模型去取到Goods的數據
  const Goods = db.db.model('Goods', db.listSchema) //第一個‘db’是require來的自定義的,第二個‘db’是取到連接到mongodb的數據庫,model代指實體數據(根據schema獲取該字段下的數據,然后傳給Goods))
  ctx.body = await new Promise((resolve, reject) => {//ctx.body是ctx.response.body的縮寫,代指響應數據
    //異步,等到獲取到數據之后再將body發出去
    if (params.categoryId) {
      Goods.find({categoryId: params.categoryId},(err, docs) => {
        if (err) {
          reject(err)
        }
        resolve({
          code: 0,
          errMsg: 'success',
          data: docs
        })
      })
    } else {
      Goods.find((err, docs) => {
        if (err) {
          reject(err)
        }
        resolve({
          code: 0,
          errMsg: 'success',
          data: docs
        })
      })
    }
  })
})
復制代碼

所有的數據庫操作都是異步的操作,所以需要封裝promise來實現,由此通過POST “http://localhost3030/shop/goods/list”便可訪問本地shop數據庫了。 這里順便提一下“ctx”的使用,ctx(context)上下文,我們都知道有node.js 中有request(請求)對象和respones(響應)對象。Koa把這兩個對象封裝在ctx對象中。 參數ctx是由koa傳入的封裝了request和response的變量,我們可以通過它訪問request和response (前端通過ajax請求http獲取數據) 我們可以通過ctx請求or獲取數據庫中的數據。

Ctx.body 屬性就是發送給用戶的內容

body是http協議中的響應體,header是指響應頭

ctx.body = ctx.res.body = ctx.response.body

5.數據緩存之模型層設置

1).為什么要做數據緩存?

在這里不得不提一句數據緩存的重要性,雖然我是從本地數據庫獲取的數據,但是由于需要的數據量較多,再者前面說的性能優化還未完成,每次還是有一定的請求時間,沒必要每次打開都去請求一遍后端,渲染頁面較慢,所以需要將需要經常用到的數據做本地緩存,這樣能大大提高頁面渲染速度。

2).設置模型層

setGoodsList: function (saveHidden, total,  allSelect, noSelect, list) {
      this.saveHidden = saveHidden,
      this.totalPrice = total,
      this.allSelect = allSelect,
      this.noSelect = noSelect,
      this.goodsList = list
      var shopCarInfo = {};
      var tempNumber = 0;
      var list = [];
      shopCarInfo.shoplist = list;

      for (var i = 0; i < list.length; i++) {
        tempNumber = tempNumber + list[i].number
      }
      shopCarInfo.shopNum = tempNumber;
      wx.setStorage({
        key: "shopCarInfo",
        data: shopCarInfo
      })
    },

復制代碼

將需要做本地存儲數據的方法封裝成一個方法模型,當需要做本地存儲時,直接做引用,如今vue、react中多用到的架構思想,都對模型層封裝有一定的要求。

bindAllSelect() {
      var list = this.goodsList;
      var currentAllSelect = this.allSelect
      if (currentAllSelect) {
        list.forEach((item) => {
          item.active = false
        })
      } else {
        list.forEach((item) => {
          item.active = true
        })
      }
      this.setGoodsList(this.getSaveHide(), this.totalPrice(), !currentAllSelect, this.noSelect(), list);
    },
復制代碼

Hishop小程序工具開發公司長沙海商,是一家有著十年技術前沿的公司,我們以先進技術提供并解決各行業小程序開發,操作簡單,支持多種社群營銷活動,以及可視化模板操作,大大減少人力物力成本。

HiShop小程序工具提供多類型商城/門店小程序制作,可視化編輯 1秒生成5步上線。通過拖拽、拼接模塊布局小程序商城頁面,所看即所得,只需要美工就能做出精美商城。更多小程序商店請查看:小程序商店

電話咨詢 預約演示 0元開店
主站蜘蛛池模板: 夜夜夜夜操18岁|c=aoporm超碰国产精品|扒开腿挺进湿润的花苞hd视频|激情三区|性bbwbbw日|爱爱免费视频 | 国产草草影院一区二区三区|91视频看看|国产一级淫片=a视频免费观看|欧美一区综合|#NAME?|国产黄毛片 | 国产亚洲精=a=a在线看|玖玖在线观看视频|国产免费内射又粗又爽密桃视频|久久99精品国产麻豆蜜芽|人妻无码一区二区视频|久久99精品久久水蜜桃 | 77777五月色婷婷丁香视频|亚洲精品国产偷五月丁香小说|国产一级黄色大片|亚洲成色777777在线观看影院|四虎成人网|四虎院影亚洲永久 | 狠狠噜天天噜日日噜无码|欧美=a=av|日批视频在线看|少妇videos|免费ā片在线观看|国产成人美女=aV | 午夜精品久久久久久99热软件|久久一区视频|午夜精品视频在线观看|亚洲福利午夜|麻豆精产国品一二三区别网站|国产乱子伦视频在线播放 | 女教师大荫蒂毛茸茸|无码免费中文字幕视频|CHINESE少妇激情|久久精品国产亚洲=aV麻豆长发|亚洲第一页夜|欧美三级网站在线观看 | 91久久香蕉国产熟女线看|人成精品视频三区二区一区|99久久精品国产91久久久|婷婷影院91xxxss|26UUU另类亚洲欧美日本|69p=ao强力打造免费高清在线 | 天堂色=av|аⅴ天堂中文在线网官网|#NAME?|日本=a在线看|91免费视频网址|亚洲精品久久久久久久久久久 | 国产精品久久久久毛片|成年视频免费|未满岁18禁止在线WWW|鲁鲁鲁爽爽爽在线视频观看|国产视频一视频二|国产精品卡一 | 亚洲久久综合|久久伊甸园|青草国产超碰人人添人人碱|91资源在线播放|九九九免费观看视频|又黄又爽的免费视频 | h黄视频在线观看|日韩精品=a=a=a|高h喷水荡肉爽文np肉色学男男|99精品中文字幕|C=aOPORN成人免费公开|久热久爱 | #NAME?|久久精品一二三影院|91看剧|欧美性色欧美=a在线视频|五月婷婷激情六月|成人免费一级=a久久 | 日韩亚洲欧美中文字幕|国产精品久久久久久亚洲调教|5060网永久免费=a级毛片|人妻少妇久久久久久97人妻|国产成人无码=a区视频在线观看|欧美理论视频 | 国产精品国产三级欧美二区|四虎影视在线免费观看|日日躁夜夜躁狠狠躁夜夜躁|日本高清中文字幕一区二区三区=a|日韩精品在在线一区二区中文|久久精品一区二区三区黑人印度 | 精品久久久久久亚洲综合网站|c=aopeng人人|蜜桃婷婷|国产高潮抽搐在线观看|中文字幕亚洲专区|第四色中文综合网 | 台湾成人=av|91porny九色打屁股|日本少妇内射视频播放舔|日本一区二区在线免费观看|日韩一区精品视频一区二区|亚洲一区自拍高清亚洲精品 | pron麻豆|66lu国产在线观看|久久WWW免费人成一看片|亚洲精品乱码久久久久久久久|国语高潮无遮挡无码免费看|成人在线观看18 | 亚州性色|国产的欧美一区二区三区|中国毛片视频|久久艹在线|国产在线www|久久久精品日韩免费观看 | 亚洲精品无码成人=a片|国产美女口爆吞精普通话|国产精品国产三级国产专播i12|91精品国产一区自在线拍|日韩特级|成人在线免费观看小视频 | 少妇被躁爽到高潮无码文|人人看人人摸|99国产欧美久久久精品|亚洲精品无码一区二区三区久久久|国产91导航|毛片在线网址 | 国产极品美女高潮无套软件|亚洲精品视频区|免费精品一区二区三区在线观看|国产SM调教折磨视频|娇妻在厨房被朋友玩得呻吟|伊人成色综合人夜夜久久 | 蜜臀=aⅴ国产精品久久久国产老师|中文在线一区二区三区|小宝极品内射国产在线|#NAME?|影音先锋啪啪=aV资源网站|国产精品久久久久网站 | 国产v=a无码高清|亚州=av免费|免费的网站www|国内外成人免费在线视频|日韩精品影院|一本无码=aV中文出轨人妻 | 在线看免费观看=av|十九岁大学生日本在线播放|91在线看视频|欧美日韩国产综合新一区|韩日黄色毛片|刘亦菲精品国产亚洲人成 | 日韩人妻无码精品=a片免费不卡|国产亚洲综合99久久系列|国产影视精品一区二区三区|午夜理论片一级毛片免费|亚洲,国产,欧美在线|久久曰视频 | 国产成人=aⅴ|日韩一区二区福利视频|日韩在线视频看看|国产剧情一区|色猫咪=aV在线网址|一级免费在线 | 国产成人毛片在线视频软件|日韩欧美一区二区三区不卡在线|中文亚洲字幕|91=av在线影院|涩涩视频在线看|欧美日韩在线观看二区视频 | 国产婷婷综合在线视频中文|人人超人人超碰超国产97超碰|一区二区动漫|中国农村毛片免费播放|久久综合久久久久88|男女猛烈啪啪无遮挡免费观看 | 免费无码又爽又刺激高潮的动漫|欧美日日日|亚洲=aV无码一区二区三区在线播放|国产九九=av|中文字幕无码视频专区|中文字幕一区二区三区手机版 | 91视频网国产|粗大猛烈进出高潮视频|精品国产乱码久久久人妻|亚洲精品无码久久毛片波多野吉衣|成人久久免费视频|国产美女自拍 | 久久久91视频|99三级|水蜜桃视频在线免费观看|黄色国产网站在线观看|含羞草家庭影院|久久久欧美国产精品人妻噜噜 | 欧美一区二区三区视频在线观看|日韩不卡高清|成人午夜视频无码免费视频|一道本道加勒比天天看|欧美成年人视频在线观看|日本中文字幕乱码免费 51久久夜色精品国产水果派解说|国产欧美日韩视频免费|国产96在线亚洲|人妻无码中文字幕免费视频蜜桃|成人=a片产无码免费视频奶头鸭度|亚洲已满18点击进入在线看片 | 激情综合欧美|日本一区欧美|97色伦欧美一区二区日韩|国产东北女人做受=av|又色又爽又黄又粗暴的小说|中文字幕无码日韩欧毛 | 国产一级淫片=a免费播放口欧美|久久久久国产视频|#NAME?|9色国产精品|9免费视频|91在线网址 | 艳魔大战4春荡女淫|97超碰免费观看|台湾佬成人网|亚洲性爱视频|无码精品一区二区三区免费视频|国产污视频在线播放 | 成人一区二区三区免费视频|日本=a=a=a=a片毛片免费观蜜桃|在线观看亚洲欧美|日本一夲道无码不卡免费视频|穿乳环蒂环上锁调教老师|国产成人综合一区二区三区 | 91大片淫黄大片在线天堂|国内国产精品久久|91cc.live最新国产|成人=aⅴ视频|v=a在线|国产成人免费视 | 亚洲在女同久久中文字幕|日本性一区二区|人妻精品久久久久中文字幕69|综合久久一区二区|无码观看=a=a=a=a=a=a=a=a片|在线影院免费观看 | 亚洲国产精品99|曰本女人牲交视频免费|国产成人8x人网站在线视频|精品无码一区在线观看|毛片一区|jk自慰到不停喷水 | 搡的我好爽视频免费观看野战|一级黄色国产视频|日本理伦片午夜理伦片|北条麻妃国产九九九精品小说|亚洲97色|亚洲人成伊人成综合无码 |