怎么用mpvue+koa+mongodb开发商城小程序
本篇内容主要讲解"怎么用mpvue+koa+mongodb开发商城小程序",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么用mpvue+koa+mongodb开发商城小程序"吧!
技术栈
前端: 微信小程序、mpvue
后端:koa
数据库:mongodb 数据库可视化工具:Robo3T
商城小程序开跑
一个基本的商城小程序,包含了前端的首页、分类、购物车、我的(订单)四个tab页,后端的数据定义、分类、和存取。各有其色,我在下面就相应介绍一些主要功能、对比原生小程序和vue.js所踩到的坑还有后端数据库的功能应用。 想了解或者有何问题都可以去 作品源码 中了解哦。
成果分享
一、前台页面及功能
1. 谈组件封装
举个栗子说,首页由三部分组成:头部轮播推荐+中间横向滑动推荐+纵向滚动商品list。这三部分,几乎是所有商城类app必需的功能了。头部的轮播推荐、中间的横向滑动式推荐的封装,我们都知道,诸如此类的功能组件,在各app上基本都少不了,最初学vue最先有所体会的,便是组件代码复用性高的特点,在进行一些组件复用迁移至别的组件或页面时,可能都不需要改动代码或者改动少量代码就可以直接使用,可以说是相当方便了,对于mpvue组件内仍然支持原生小程序的swiper与scroll,两者兼容后,对于熟知小程序和vue的开发者,这项功能可以很高效率地完成。
最后主页面文件就是由一个个组件组成,可读性很强了,对于初学者来说,模块封装的思想是首先就得具备的了。
—— 热门商品 ——复制代码不过关于组件封装与组合的问题,由于最近有研究vue性能优化和用户体验的一些知识点,考虑了一个比较严肃的问题:
先看一下常见的vue写法:在html里放一个app组件,app组件里又引用了其他的子组件,形成一棵以app为根节点的组件树:
复制代码 而这种做法就引发了性能问题,要初始化一个父组件,必然需要先初始化它的子组件,而子组件又有它自己的子组件。那么要初始化根标签,就需要从底层开始冒泡,将页面所有组件都初始化完。所以我们的页面会在所有组件都初始化完才开始显示。
这个结果显然不是我们要的,用户每次点开页面,还要面对一阵子的空白和响应,因为页面启动后不止要响应初始化页面的组件,还有包含在app里的其他组件,这样严重拖慢了页面打开的速度。
更好的结果是页面可以从上到下按顺序流式渲染,这样可能总体时间增长了,但首屏时间缩减,在用户看来,页面打开速度就更快了。网上一些办法大同小异,各有优缺点,所以...本人也在疯狂试验中,静待好消息。
**2.Class、Style的绑定 **
在不同父组件中引用同一子组件时,但是各自需要接收绑定的动态样式去呈现不同的样式,在绑定css style样式这一关上,踩了个大坑:mpvue居然不支持用object的形式传style,起先处于样式一直上不去的抓狂当中,网上对于mpvue这方面的细节也少之又少,后来查找了许多地方,发现class和style的绑定都是不支持classObj和styleObj形式,就尝试用了字符串,果然...改代码改到怀疑人生,结果你告诉我人生起步就是错误,怎能不心痛?...
解决:
复制代码3. "v-for嵌套"陷阱
在做vue项目的时候难免会用到循环,需要用到index索引值,但是v-for在嵌套时index没办法重复用,内循环与外循环不能共用一个index。
复制代码 而给内循环再加上另一个索引,便没有报错:
复制代码 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-routerconst 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); },复制代码到此,相信大家对"怎么用mpvue+koa+mongodb开发商城小程序"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
数据 组件 代码 数据库 函数 页面 程序 对象 方法 模型 封装 路由 指向 商品 实例 数据表 商城 功能 周期 生命 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 2022无尽之海服务器人多吗 数据库助理 数据库dll脚本文件 网络安全信息工作台账 网络安全系列培训名称 music多媒体服务器 2019年重庆网络安全周 用数据库实现购物车 中国光大银行软件开发中心合肥 梦幻西游彩云之南服务器人多吗 wps跨文件提取数据库 手游梦幻西游安卓服务器 数据库学生管理系统建表 银行流水数据如何导入数据库 云霄县戚日网络技术工作室 合肥清默网络技术 电子临床数据库研究报告 怎么把手机变成云端数据库 从别的表中读取数据库 网络安全红线案例 淘宝代理服务器犯法吗 可以修改数据库表属性的命令 西藏民族大学网络安全技能大赛 可演进知识中心智能网络技术 关于网络安全的插画 技嘉x99服务器主板 互联网证券 金融科技 英勇联盟提示服务器之间出现问题 东数西算涉及网络安全吗 什么是电子邮箱的服务器