commit | author | age
|
7ee3f4
|
1 |
[TOC] |
Z |
2 |
|
|
3 |
# 禾匠商城v4小程序端 |
|
4 |
|
|
5 |
##前置条件 |
|
6 |
|
|
7 |
###开发者需要掌握的 |
|
8 |
|
|
9 |
- Html |
|
10 |
|
|
11 |
- Javascript(ES6) |
|
12 |
|
|
13 |
- CSS(Sass) |
|
14 |
|
|
15 |
- 小程序开发(微信为主、支付宝、百度、字节跳动) |
|
16 |
|
|
17 |
- <a href="https://cn.vuejs.org/index.html" target="_blank">Vue</a> |
|
18 |
|
|
19 |
- <a href="https://uniapp.dcloud.io/" target="_blank">Uni-app</a> |
|
20 |
|
|
21 |
### 运行环境 |
|
22 |
|
|
23 |
Node.js + 小程序开发者工具 |
|
24 |
|
|
25 |
## 安装、运行 |
|
26 |
|
|
27 |
1. 命令行切换到代码目录下,执行以下命令安装依赖 |
|
28 |
|
|
29 |
```shell script |
|
30 |
npm install |
|
31 |
``` |
|
32 |
|
|
33 |
2. 创建配置下面两个文件 |
|
34 |
|
|
35 |
/src/siteInfo.js文件 |
|
36 |
小程序配置如下: |
|
37 |
```javascript |
|
38 |
module.exports = { |
|
39 |
'acid': -1, |
|
40 |
'version': '1.0.0', |
|
41 |
'siteroot': 'http://localhost/app/index.php', |
|
42 |
'apiroot': 'https://localhost/web/index.php?_mall_id=1', |
|
43 |
}; |
|
44 |
``` |
|
45 |
h5配置如下: |
|
46 |
```javascript |
|
47 |
let siteInfo = { |
|
48 |
'acid': -1, |
|
49 |
'version': '1.0.0', |
|
50 |
'apiroot': 'https://localhost/web/index.php?_mall_id=1', |
|
51 |
'id': '1', |
|
52 |
}; |
|
53 |
``` |
|
54 |
|
|
55 |
修改`apiroot`成自己的服务器路径,`_mall_id`可从后台的`小程序商城`列表获取到ID,id为后台的`小程序商城`列表获取到ID |
|
56 |
|
|
57 |
/src/manifest.json文件 |
|
58 |
|
|
59 |
```json |
|
60 |
{ |
|
61 |
"name": "zjhj_bd_app", |
|
62 |
"appid": "", |
|
63 |
"description": "", |
|
64 |
"versionName": "1.0.0", |
|
65 |
"versionCode": "100", |
|
66 |
"transformPx": false, |
|
67 |
"uniStatistics": { |
|
68 |
"enable": false |
|
69 |
}, |
|
70 |
"app-plus": { |
|
71 |
}, |
|
72 |
"quickapp": { |
|
73 |
}, |
|
74 |
"mp-weixin": { |
|
75 |
"appid": "", |
|
76 |
"setting": { |
|
77 |
"urlCheck": false |
|
78 |
}, |
|
79 |
"usingComponents": true, |
|
80 |
"permission": { |
|
81 |
"scope.userLocation": { |
|
82 |
"desc": "请求获取您的位置信息" |
|
83 |
} |
|
84 |
} |
|
85 |
}, |
|
86 |
"mp-alipay": { |
|
87 |
"usingComponents": true |
|
88 |
}, |
|
89 |
"mp-baidu": { |
|
90 |
"appid": "", |
|
91 |
"usingComponents": true |
|
92 |
}, |
|
93 |
"mp-toutiao": { |
|
94 |
"appid": "", |
|
95 |
"usingComponents": true, |
|
96 |
"urlCheck": false |
|
97 |
}, |
|
98 |
"mp-qq": { |
|
99 |
"usingComponents": true |
|
100 |
}, |
|
101 |
"h5": { |
|
102 |
"async": { |
|
103 |
"loading": "AsyncLoading", |
|
104 |
"error": "AsyncError", |
|
105 |
"delay": 2000, |
|
106 |
"timeout": 10000 |
|
107 |
}, |
|
108 |
"uniStatistics" : { |
|
109 |
"enable" : true |
|
110 |
}, |
|
111 |
"publicPath" : "/addons/zjhj_bd/h5/", |
|
112 |
"router" : { |
|
113 |
"base" : "/addons/zjhj_bd/h5/", |
|
114 |
"mode" : "hash" |
|
115 |
}, |
|
116 |
"sdkConfigs": { |
|
117 |
"maps": { |
|
118 |
"qqmap": { |
|
119 |
// 腾讯地图秘钥(key)https://lbs.qq.com/dev/console/key/manage |
|
120 |
"key": "" |
|
121 |
} |
|
122 |
} |
|
123 |
} |
|
124 |
}, |
|
125 |
} |
|
126 |
``` |
|
127 |
|
|
128 |
`mp-weixin/appid`填写上微信小程序的appid |
|
129 |
|
|
130 |
h5编译时需要注意文件路径问题:目前需要将h5编译后的文件解压到`域名根目录/addons/zjhj_bd/h5/`路径下; |
|
131 |
|
|
132 |
3. 编译代码 |
|
133 |
|
|
134 |
编译微信小程序 |
|
135 |
|
|
136 |
```shell script |
|
137 |
npm run dev:mp-weixin |
|
138 |
``` |
|
139 |
|
|
140 |
会在dist/dev下生成mp-weixin文件夹,用微信开发者工具打开即可预览小程序 |
|
141 |
|
|
142 |
各个平台编译命令: |
|
143 |
``` |
|
144 |
// 微信 |
|
145 |
npm run dev:mp-weixin |
|
146 |
|
|
147 |
// 支付宝 |
|
148 |
npm run dev:mp-alipay |
|
149 |
|
|
150 |
// 百度 |
|
151 |
npm run dev:mp-baidu |
|
152 |
|
|
153 |
// 字节跳动 |
|
154 |
npm run dev:mp-toutiao |
|
155 |
``` |
|
156 |
|
|
157 |
## 规范 |
|
158 |
|
|
159 |
### Git规范 |
|
160 |
|
|
161 |
- dev为公共开发分支,开发提交的内容请提交至dev; |
|
162 |
|
|
163 |
- git提交尽量以每一项修改提交一次,尽量不要多项修改一次提交,备注信息请勿提交“111”,“aaaa”这样不明意思的内容; |
|
164 |
|
|
165 |
- 项目发布后,涉及到比较大的改动或新功能开发,建议自己创建分支进行开发; |
|
166 |
|
|
167 |
- 自己创建的分支需要经常把dev合并到自己的分支,以面差异过多产生冲突; |
|
168 |
|
|
169 |
- 自己分支开发的内容确认开发完成需要测试时,合并到dev分支; |
|
170 |
|
|
171 |
### 代码基础规范 |
|
172 |
|
|
173 |
- 必须以4个空格缩进,并保持代码缩进整齐; |
|
174 |
|
|
175 |
- 代码结尾必须以分号结尾; |
|
176 |
|
|
177 |
- Html代码标签属性使用双引号,示例 |
|
178 |
|
|
179 |
```html |
|
180 |
<view msg="hello"></view><!--正确示范--> |
|
181 |
<view msg='hello'></view><!--错误示范--> |
|
182 |
``` |
|
183 |
|
|
184 |
- JavaScript代码字符串优先使用''或``,示例 |
|
185 |
|
|
186 |
```javascript |
|
187 |
const str = 'hello'; // 正确示范 |
|
188 |
const str = `hello`; // 正确示范 |
|
189 |
|
|
190 |
const str = "hello"; // 错误示范 |
|
191 |
``` |
|
192 |
|
|
193 |
- 组件命名使用app-xxx-xxx的格式; |
|
194 |
|
|
195 |
### 开发基础组件 |
|
196 |
|
|
197 |
请给写的公共组件写一个使用文档,在doc/components.md。 |
|
198 |
|
|
199 |
### FormId记录 |
|
200 |
|
|
201 |
尽可能的使用app-form-id组件套可点击的位置,以记录formid发送模板消息用。 |
|
202 |
|
|
203 |
### 样式 |
|
204 |
|
|
205 |
- 全局scss 变量定义 ./uni.scss; |
|
206 |
|
|
207 |
- 主题颜色 ./static/css/themeColor.scss; |
|
208 |
|
|
209 |
- 弹性布局 ./static/css/flex.scss; |
|
210 |
|
|
211 |
### 静态图片 |
|
212 |
|
|
213 |
- 通用图片 ./static/image/ |
|
214 |
|
|
215 |
- 单独图片 组件下或页面下 ./image/ |
|
216 |
|
|
217 |
### 层级(z-index) |
|
218 |
|
|
219 |
- 普通悬浮组件(低于底部导航):<1500 |
|
220 |
|
|
221 |
- 底部导航:1500 |
|
222 |
|
|
223 |
- 悬浮组件(高于底部导航):>1500 |
|
224 |
|
|
225 |
## 代码说明 |
|
226 |
|
|
227 |
### 目录结构 |
|
228 |
|
|
229 |
/src目录 |
|
230 |
|
|
231 |
``` |
|
232 |
components // 公共组件 |
|
233 |
core // 小程序核心代码 |
|
234 |
└── apiUrl.js // 服务器端API接口配置 |
|
235 |
pages // 页面代码 |
|
236 |
plugins // 插件代码 |
|
237 |
static // 图片、样式 |
|
238 |
store // vuex |
|
239 |
App.vue // 小程序生命周期控制 |
|
240 |
main.js // 入口文件 |
|
241 |
manifest.json // 小程序配置 |
|
242 |
pages.json // 页面路由配置 |
|
243 |
siteinfo.js // 服务器路径配置 |
|
244 |
uni.scss // 全局样式 |
|
245 |
``` |
|
246 |
|
|
247 |
### 生命周期 |
|
248 |
|
|
249 |
页面的生命周期使用页面的生命周期,参见 |
|
250 |
|
|
251 |
[https://uniapp.dcloud.io/frame?id=页面生命周期] |
|
252 |
|
|
253 |
组件生命周期使用vue组件的生命周期,参见 |
|
254 |
|
|
255 |
[https://cn.vuejs.org/v2/guide/instance.html#实例生命周期钩子] |
|
256 |
|
|
257 |
### 主题色 |
|
258 |
```html |
|
259 |
<!-- 组件形式--> |
|
260 |
<component :theme="theme"></component> |
|
261 |
<!-- 标签形式--> |
|
262 |
<view :class="[`${theme}-background`, `${theme}-color`]"></view> |
|
263 |
``` |
|
264 |
|
|
265 |
````javascript |
|
266 |
export default { |
|
267 |
props: { |
|
268 |
theme: { |
|
269 |
default: 'classic-red', // 统一整个颜色为默认主题色 |
|
270 |
type: String, |
|
271 |
} |
|
272 |
} |
|
273 |
} |
|
274 |
```` |
|
275 |
### 公共代码 - app-layout |
|
276 |
- 每一个page页面请用,如下代码书写: |
|
277 |
````html |
|
278 |
<template> |
|
279 |
<app-layout> |
|
280 |
</app-layout> |
|
281 |
</template> |
|
282 |
```` |
|
283 |
|
|
284 |
### 组件使用规范 |
|
285 |
|
|
286 |
#### 样式 穿透 |
|
287 |
- 在vue文件中的style标签上,有一个特殊的属性:scoped。 |
|
288 |
当一个style标签拥有scoped属性时, |
|
289 |
它的CSS样式就只能作用于当前的组件, |
|
290 |
也就是说,该样式只能适用于当前组件元素。 |
|
291 |
通过该属性,可以使得组件之间的样式不互相污染。 |
|
292 |
如果一个项目中的所有style标签全部加上了scoped,相当于实现了样式的模块化。 |
|
293 |
````html |
|
294 |
<style> |
|
295 |
/* global styles */ |
|
296 |
</style> |
|
297 |
```` |
|
298 |
|
|
299 |
````html |
|
300 |
<style scoped> |
|
301 |
/* local styles */ |
|
302 |
</style> |
|
303 |
```` |
|
304 |
|
|
305 |
- 编译前 |
|
306 |
|
|
307 |
````html |
|
308 |
<style scoped> |
|
309 |
.example { |
|
310 |
color: red; |
|
311 |
} |
|
312 |
</style> |
|
313 |
|
|
314 |
<template> |
|
315 |
<div class="example">hi</div> |
|
316 |
</template> |
|
317 |
|
|
318 |
```` |
|
319 |
|
|
320 |
- 编译后 |
|
321 |
|
|
322 |
````html |
|
323 |
<style> |
|
324 |
.example.data-v-5558831a. { |
|
325 |
color: red; |
|
326 |
} |
|
327 |
</style> |
|
328 |
|
|
329 |
<template> |
|
330 |
<div class="example" data-v-5558831a>hi</div> |
|
331 |
</template> |
|
332 |
```` |
|
333 |
|
|
334 |
穿透方法 |
|
335 |
```` |
|
336 |
<style scoped> |
|
337 |
外层 /deep/ 第三方组件 { |
|
338 |
样式 |
|
339 |
} |
|
340 |
</style> |
|
341 |
```` |
|
342 |
### 组件使用方法 |
|
343 |
- 开发是在组件外部套上 view 标签 目的: 平台样式兼容处理 |
|
344 |
|
|
345 |
````html |
|
346 |
<template> |
|
347 |
<app-layout> |
|
348 |
<view> |
|
349 |
<app-component></app-component> |
|
350 |
</view> |
|
351 |
</app-layout> |
|
352 |
</template> |
|
353 |
```` |
|
354 |
|
|
355 |
````javascript |
|
356 |
import appComponent from "../component/app-component.vue"; |
|
357 |
export default { |
|
358 |
components: { |
|
359 |
'app-component': appComponent, |
|
360 |
} |
|
361 |
} |
|
362 |
```` |
|
363 |
### 全局组件挂载 |
|
364 |
- uni-app 支持配置全局组件,需在 main.js 里进行全局注册,注册后就可在所有页面里使用该组件。 |
|
365 |
|
|
366 |
main.js 里进行全局导入和注册 |
|
367 |
````javascript |
|
368 |
import Vue from 'vue'; |
|
369 |
import pageHead from './components/page-head.vue'; |
|
370 |
Vue.component('page-head',pageHead); |
|
371 |
```` |
|
372 |
index.vue 里可直接使用组件 |
|
373 |
````html |
|
374 |
<template> |
|
375 |
<view> |
|
376 |
<page-head></page-head> |
|
377 |
</view> |
|
378 |
</template> |
|
379 |
```` |
|
380 |
|
|
381 |
### 网络请求 |
|
382 |
- api request 已挂载在全局 |
|
383 |
````javascript |
|
384 |
Vue.use({ |
|
385 |
install(Vue, options) { |
|
386 |
// 接口 路径 |
|
387 |
Vue.prototype.$api = Api; |
|
388 |
// 请求 |
|
389 |
Vue.prototype.$request = request; |
|
390 |
}, |
|
391 |
}); |
|
392 |
```` |
|
393 |
|
|
394 |
- 使用方法 |
|
395 |
````javascript |
|
396 |
this.$request({ |
|
397 |
url: this.$api.index.config, |
|
398 |
}); |
|
399 |
```` |
|
400 |
|
|
401 |
### vuex |
|
402 |
|
|
403 |
- modules 模块化 以及 组件中引入 mapGetters、mapActions 和 mapStates的使用 |
|
404 |
index.js |
|
405 |
````javascript |
|
406 |
import Vue from 'vue'; |
|
407 |
import Vuex from 'vuex'; |
|
408 |
// 模块引入 |
|
409 |
import user from './modules/user.js'; |
|
410 |
import mallConfig from './modules/mallConfig.js'; |
|
411 |
|
|
412 |
Vue.use(Vuex); |
|
413 |
|
|
414 |
export default new Vuex.Store({ |
|
415 |
modules:{ |
|
416 |
user: user, |
|
417 |
mallConfig: mallConfig, |
|
418 |
} |
|
419 |
}); |
|
420 |
```` |
|
421 |
|
|
422 |
````javascript |
|
423 |
// user.js |
|
424 |
const state={ |
|
425 |
userName: '', //初始化数据 |
|
426 |
}; |
|
427 |
const getters={ |
|
428 |
getUserName(state){ // 获取数据 |
|
429 |
return state.userName; |
|
430 |
} |
|
431 |
}; |
|
432 |
const mutations={// 只能做同步操作 |
|
433 |
setUserName(state,data){ //如何变化collects,插入items |
|
434 |
state.userName = data |
|
435 |
} |
|
436 |
}; |
|
437 |
const actions={// 可以做异步操作 |
|
438 |
actionsUserName(context,item){ // 调用setUserName ,传入数据形参item 对应到items |
|
439 |
return new Promise((resolve, reject) => { |
|
440 |
context.commit('setUserName',item); |
|
441 |
}); |
|
442 |
} |
|
443 |
}; |
|
444 |
export default { |
|
445 |
namespaced:true,//用于在全局引用此文件里的方法时标识这一个的文件名 |
|
446 |
state, |
|
447 |
getters, |
|
448 |
mutations, |
|
449 |
actions |
|
450 |
} |
|
451 |
```` |
|
452 |
````javascript |
|
453 |
import { mapState,mapGetters,mapActions } from 'vuex'; |
|
454 |
export default { |
|
455 |
computed: { |
|
456 |
...mapState({ //ES6的语法,意思是state里有多少属性值我可以在这里放多少属性值 |
|
457 |
userName: state=> state.user.userName |
|
458 |
}), |
|
459 |
...mapGetters('user',{ //用mapGetters来获取user.js里面的getters |
|
460 |
userName: 'getUserName' |
|
461 |
}) |
|
462 |
}, |
|
463 |
mounted() { |
|
464 |
this.$store.dispatch('user/actionsUserName'); // 执行 user.js里的 actions里的方法 |
|
465 |
}, |
|
466 |
methods: { |
|
467 |
...mapActions('user',[ //user是指modules文件夹下的user.js |
|
468 |
'actionsUserName' //user.js文件中的actions里的方法,在上面的@click中执行并传入实参 |
|
469 |
]) |
|
470 |
} |
|
471 |
} |
|
472 |
```` |
|
473 |
|
|
474 |
### 条件编译 |
|
475 |
|
|
476 |
不同平台下编译出不同代码 |
|
477 |
|
|
478 |
[https://uniapp.dcloud.io/platform](https://uniapp.dcloud.io/platform) |