原項目使用微信小程序配合ThinkPHP5.0打造的微信小程序商城,做爲一名「中端工程師」來說可以使用javascript先後一塊兒梭也是工做之餘很是愉快的事情。因此若是你也想梭一把,那麼能夠繼續往下看。javascript
github項目地址css
1.前端部分沒有100%還原設計稿,由於壓根就沒有設計稿。惟一的標準就是本身的「像素眼」。
2.做爲WEB項目天然而然就閹割了微信的登陸與支付體系。固然登陸體系也許會加上。
3.後端部分沒有作嚴格的容錯處理,這裏更多的是提供一些問題的解決方法和分享本身遇到的坑兒。html
前端部分好像沒有什麼好說的了,網上vue全家桶項目一搜一大把。這裏主要分享一下從前端角度如何分解產品設計稿以及css模塊化的處理。本篇文章將重點放在服務端上。前端
不知道其餘小夥伴拿到設計稿是如何開始的,記得纔開始寫前端的時候也是根據設計稿從上到下,從左到右一步一步實現。不過每每這樣的開發流程遇到大的需求變動,或是產品同窗提不切實際需求的時候是很是頭痛的。這裏提一句,前端小夥伴必定要多多參加產品需求會,一方面能夠增長對公司業務的理解,另外一方面能夠把產品同窗不切實際的需求扼殺在搖籃中,防止拍腦殼決策出現。vue
分解設計稿
「零食商販」項目雖然頁面有多個,可是咱們分解設計稿就會發現其實該項目由這幾個部分組成。java
Header與Footer
這一部分稱爲公共部分。基本上每一個頁面都由header、footer以及中間主要內容組成。node
layout
這一部分稱爲「基模塊」。也就是頁面大部分都是由該模塊組合而成,無非是一些內容的增減,實際開發中徹底能夠經過數據以及css達到各個頁面個性化定製需求。mysql
以上三個頁面都同樣,只是換了馬甲。
結構抽象出來應該就是這樣:ios
//vue模板 <template> <div> <!-- 小標題 --> <p>{{ title }}</p> <slot></slot> <div> <!-- 產品模塊 --> <div> <img src="" alt="" > <p >{{ item.name }}</p> <p >{{ item.price }}</p> </div> </div> </div> </template>
雖然vue提供了scope來方便編寫組件內部的css,防止css名相互污染。但有時候scope形成的做用域問題不方便調試。因此這裏採用了一樣流行的CSS Modules。
開啓方式也很簡單,若是是使用vue-cli方式構建的vue項目,只須要兩步便可開啓:git
進入文件夾build/vue-loader-conf.js
module.exports = { // css模塊化 cssModules: { // 經過給類名加入惟一前綴防止類名衝突 localIdentName: '[name]---[local]---[hash:base64:5]', camelCase: true } }
在每一個組件中申明css modules並使用
<template> //$style部分將會替換爲'[name]---[local]---[hash:base64:5]' <div :class="$style.header"></div> </template> <style lang='scss' module> .header{ color:blue } </style>
css modules 的核心原理就是經過加入惟一的class類名從而防止css類名衝突。本質上的效果與scope是同樣的。
項目寫到一半,才發現須要一款符合微信官方風格的UI組件,雖然官方UI組件顏值上並不高。可是爲了視覺上的統一,又苦於網上沒有找到過於簡陋的UI組件,因此本身封裝了一個。目前只有picker組件和基於picker組件的地址選擇組件。
npm 命令直接安裝,本項目默認是安裝好了的。由於簡陋因此也就不提供什麼文檔了...... 具體用法能夠看項目內部實現。
npm install only-ui --save
項目後端部分採用koa2搭配mysql數據實現,koa2官網是這樣介紹的:
Koa 是一個新的 web 框架,由 Express 幕後的原班人馬打造, 致力於成爲 web 應用和 API 開發領域中的一個更小、更富有表現力、更健壯的基石。 經過利用 async 函數,Koa 幫你丟棄回調函數,並有力地加強錯誤處理。 Koa 並無捆綁任何中間件, 而是提供了一套優雅的方法,幫助您快速而愉快地編寫服務端應用程序。
正是由於koa2輕量,沒有一些官方性的約束,你能夠很方便搭建本身的前端項目。但同時也帶來了一些問題,「一千我的就有一千種koa MVC的寫法」,因此若是是大一點項目或是團隊項目仍是比較推薦egg.js來編寫。
//經過koa-generator快速搭建koa2服務 npm install -g koa-generator //建立項目 輸入項目名稱 koa2 -e [項目名稱] //安裝依賴 npm install
這樣咱們基本上建立了一個比較簡單的koa2項目,咱們來看一下如今已經安裝了哪些依賴
"dependencies": { "debug": "^2.6.3", "ejs": "~2.3.3", //ejs模板,由於咱們建立項目的時候用的ejs "koa": "^2.2.0", "koa-bodyparser": "^3.2.0", //解析request "koa-convert": "^1.2.0", "koa-json": "^2.0.2", //格式化json數據 "koa-logger": "^2.0.1", //系統日誌 "koa-onerror": "^1.2.1", //錯誤處理 "koa-router": "^7.1.1", //路由 "koa-static": "^3.0.0", //靜態資源處理 "koa-views": "^5.2.1"//模板渲染 }, "devDependencies": { "nodemon": "^1.8.1" //能夠隨時監聽服務端文件改動,並更新 }
前面說了,koa就像一塊電腦主板同樣,須要什麼東西本身能夠往上面加。這裏有更多中間件,若是仍是沒有你須要的,你徹底能夠本身寫一個造福社區。
只有以上的中間件仍是不夠的,好比我並不但願使用require語法導入模塊因此咱們換成 es6 modules方式導入。這裏還須要安裝:
"babel-core": "^6.26.3", "babel-preset-env": "^1.7.0", "babel-preset-es2015": "^6.24.1", "babel-register": "^6.26.0",
同時修改項目結構
//index.js // 啓動文件 require('babel-register') ({ 'presets':['env'] }) require('./app.js')
這樣咱們就能夠在主文件中使用import導入咱們須要的模塊。(中間件的導入在在項目中有清晰的註釋)
咱們來嘗試啓動一下koa2服務,啓動以前要修改一下npm(你怕嗎) script
"scripts": { "start": "nodemon index.js", //使用nodemon 啓動index文件 },
服務端開發怎麼能少了數據庫,不知道是否是錯覺,koa項目好像更多的是配合mongodb來使用。本項目使用mysql徹底是由於本身的習慣,再一個使用mongodb處理複雜一點的數據表間關係確實有點頭痛。。。
咱們在這裏引入sequelize來操做mysql,畢竟使用原生sql顯得不是那麼優雅!什麼是sequelize?
Sequelize 是一個基於 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, SQLite 和 Microsoft SQL Server. 它具備強大的事務支持, 關聯關係, 讀取和複製等功能.
通俗一點說,就比如Java中的hibernate,mongodb中的mongoose。讓咱們以面向對象的方式操做數據庫。
如今讓咱們來安裝sequelize。mysql的安裝
// 安裝sequelize $ npm install --save sequelize // 安裝驅動 $ npm install --save mysql2
既然咱們使用sequelize操做數據庫,那麼一番基本的配置必定是要有的。
//config.js // sequelize配置文件 export default { // 數據庫名稱 database: '', // 用戶名 username: '', // 密碼 password: '', // 地址 host: '127.0.0.1', // 使用什麼數據庫 dialect: 'mysql', // 鏈接池 pool: { max: 5, min: 0, acquire: 30000, idle: 10000 }, // 數據表全局配置 define:{ //是否凍結表名,最好設置爲true,要不sequelize會自動給表名加上覆數s形成查詢數據失敗。 //mongoose也有這樣的問題... freezeTableName:true, // 是否爲表添加 createdAt 和 updatedAt 字段 // createdAt 記錄表的建立時間 // updatedAt 記錄字段更新時間 timestamps:false, // 是否爲表添加 deletedAt 字段 // 在平常開發中刪除數據記錄是一大禁忌,所以咱們刪除數據並不會真正刪除,而是爲他添加 // deletedAt字段 paranoid:false, //是否開啓op operatorsAliases: false }, // 時區 timezone: '+08:00' }
如此一番操做,sequelize已經與mysql創建起聯繫,但還沒法工做,咱們須要給數據表創建模型。創建模型以前咱們導入剛剛已經配置好的文件。以下圖
index.js中導入咱們的配置config.js文件,其餘的文件都是模型(能夠把它理解爲數據庫中的表,讓咱們更好操做它)。
咱們在navicat中看到的表長這個樣子
咱們的模型長這個樣子:
//banner.js // banner 模型 export default (sequelize, DataTypes) => { //這裏的banner爲你的數據表名 return sequelize.define('banner', { id: { //定義類型 type: DataTypes.INTEGER(), //主鍵 primaryKey: true }, productsId: { //定義類型 type: DataTypes.INTEGER(), }, img_id: { //定義類型 type: DataTypes.INTEGER(), } }) }
而後導入到index.js中統一管理(必定要讓你的全部模型在同一個sequelize實例下,曾經這個問題困擾了我好久。。。)
//index.js import Sequelize from 'sequelize' import config from '../config.js' // 實例化sequelize export const sequelize = new Sequelize(config) // 導入模型統一管理(推薦使用官方方法) export const Banner = sequelize.import(__dirname + '/banners.js')
表與表之間無外乎:
一對一 belongsto
外鍵一對一 hasone
一對多 hasmany
多對多 belongsToMany
拿咱們項目中的banner與image來舉例,banner指向惟一image,image對應惟一banner那麼他們之間關係就爲一對一。
//定義關係 Banner.belongsTo(Image, { foreignKey: 'img_id', targetKey: 'id' })
如今咱們創建了模型也定義了模型間關係,如今咱們開始來使用。
仍是以banner爲例
//api/banner.js // banner接口 import Router from 'koa-router' // 引入用戶模型 import { Banner,Image } from '../dbs/models/index.js' //定義接口前綴 let router = new Router({ prefix:'/banner' }) //暴露給前端的接口 router.get('/', async (ctx,next)=>{ let banner = await Banner.findAll({ //聲明要包含的模型,以前聲明的關係將在這裏發揮做用 include:[{ model:Image }], //過濾不須要的數據 attributes:{ exclude:['img_id'] } }) //最終返回的數據 ctx.body = { banner } }) export default router
最後咱們須要把路由導入到主文件中。
//app.js //引入 import banner from './api/banner.js' //使用 app.use(banner.routes()).use(banner.allowedMethods())
如今你能夠在前端經過axios訪問你的數據接口了,咱們看一下最終執行效果。
sequelize已經自動幫咱們生成了sql語句:
postman中的數據:
其餘更詳細的內容能夠查看mini-shop!