前面已将基础知识准备的差不多了,下面实际做一个小程序。

一、目标

用于上传照片和文字。

2个主要页面:我me,设置set

二、开始制作

1、打开微信开发者工具(我用的1.02.1907160 Windows 64版本),点+号,新建项目diary,选择目录E:\wxDEV\diary,填入从微信开发平台申请到的AppID,开发模式默认为小程序,后端服务选择云开发,点新建,生成了云开发QuitStart示例模板。下面在此模板基础上制作。

2、建立me   set页面,并给小程序增加tabBar。即修改E:\wxDEV\minishop\miniprogram\app.json并保存。代码如下:

  1. {
  2. "pages": [
  3. "pages/index/index",
  4. "pages/me/me",
  5. "pages/people/people",
  6. "pages/set/set"
  7. ],
  8. "window": {
  9. "backgroundColor": "#F6F6F6",
  10. "backgroundTextStyle": "light",
  11. "navigationBarBackgroundColor": "#F6F6F6",
  12. "navigationBarTitleText": "日记",
  13. "navigationBarTextStyle": "black"
  14. },
  15. "tabBar": {
  16. "backgroundColor": "#eeeeee",
  17. "position": "bottom",
  18. "list": [
  19. {
  20. "pagePath": "pages/me/me",
  21. "text": "我",
  22. "iconPath": "images/img.jpg",
  23. "selectedIconPath": "images/img.jpg"
  24. },
  25. {
  26. "pagePath": "pages/set/set",
  27. "text": "设置",
  28. "iconPath": "images/img.jpg",
  29. "selectedIconPath": "images/img.jpg"
  30. }
  31. ]
  32. },
  33. "sitemapLocation": "sitemap.json"
  34. }
  1. 同时,要在images目录中放置一张img.jpg图片(我自己画了一张)

3、我打算将现有的index页作为将来的splash页。所以先修改E:\wxDEV\diary\miniprogram\pages\index\index.js,以实现2秒后跳转me页,代码:

  1. //index.js
  2.  
  3. Page({
  4. data: {},
  5.  
  6. onLoad: function() {
  7. setTimeout(function() {
  8. wx.reLaunch({
  9. url: '../me/me',
  10. })
  11. }, )
  12.  
  13. }
  14. })

4、修改me页(为方便调试,可更改app.json中pages值的顺序,将me调整到前面)。原本想在me页上用movable-view增加可拖动的按钮样式,如下:

  1. <!--可拖动按钮-->
  2. <movable-area style="height:{{mHeight}}px;width:100%;position:fixed;z-index:999;pointer-events:none;">
  3. <movable-view direction="all" style="height: 30px; line-height:30px;width: 30px; margin-left:100%; border:2px solid lightblue;border-radius:50%;">
  4. <cover-view bindtap="writeDiary">
  5. <cover-image src='../../images/img.jpg'></cover-image>
  6. </cover-view>
  7. </movable-view>
  8. </movable-area>

结果在安卓真机上出现兼容性问题,拖动时cover-view瞬间移动,而cover-image不跟随移动,无法正常工作。(谁知道解决办法给我讲一下?)只好弃用。

云开发的云函数的独特优势在于与微信登录鉴权的无缝整合,参考:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/userinfo.html

所以,对不同用户上传内容可以用openid区分。

5.半成品的me.wxml ,代码如下:

  1. <!--pages/me/me.wxml-->
  2. <view style="display:flex;flex-direction: row-reverse;margin-right:20px;font-size:150%;"><text bindtap="writeDiary">{{inputCursor}}</text></view>
  3.  
  4. <view style="width:100%;">
  5. <!-- 上传图片 -->
  6. <view class="uploader">
  7. <view class="uploader-text" bindtap="selPic">
  8. <text>拍照或选择图片(可选)</text>
  9. </view>
  10. <view class="uploader-container" wx:if="{{imgUrl}}">
  11. <image class="uploader-image" src="{{imgUrl}}" mode="aspectFit" bindtap="previewImg"></image>
  12. </view>
  13. </view>
  14. <!-- 表单 -->
  15. <form class="formpub" bindsubmit="formSubmit" bindreset="formReset">
  16. <!-- 保存图片临时路径 -->
  17. <view class="section">
  18. <input name="img" value="{{imgUrl}}" hidden="true" />
  19. </view>
  20.  
  21. <view class="content">
  22. <view class="currentWordNumber">{{currentWordNumber|}}/{{max}}</view>
  23. <!-- 别忘了给textarea加上name属性 -->
  24. <textarea name="diaryContent" bindblur="getText" bindinput="getValueLength" show-confirm-bar='true' value="{{editText}}" bindconfirm="getText" maxlength="{{max}}" minlength="{{min}}" placeholder="内容..." auto-focus>
  25. <text class="minWord">{{minWord}}</text>
  26. </textarea>
  27. </view>
  28. <view class="tips">在上面填写内容</view>
  29.  
  30. <view class="btn-area">
  31. <button form-type="submit" style="width: 80%; margin-top: 20rpx;background-color: beige;color: black;border:2px solid lightblue;">写完了</button>
  32. </view>
  33. </form>
  34. </view>
  35.  
  36. <block wx:for="{{diarys}}" wx:key="{{index}}">
  37. <view style="display:flex;width:100%;min-height:50px;background:rgb(248, 248, 248);margin:8px;">
  38. <view style="border:20px;">
  39. <image wx:if='{{item["img"]}}' src='{{item["img"]}}'mode="widthFix" style="width:100px;"></image>
  40. </view>
  41. <view style="width:100%;border-bottom:solid 1px lightgrey;padding-left:10px;"> {{item["content"]}} </view>
  42. </view>
  43. </block>
  44. <view>
  45. <image src='../../images/img.jpg' mode="widthFix" style="width:50px"></image>
  46. </view>

me.js

  1. // pages/me/me.js
  2. Page({
  3.  
  4. /**
  5. * 页面的初始数据
  6. */
  7. data: {
  8. //以下变量也可以不写在这里,可直接在代码中声明和使用,但推荐写在这里
  9. mHeight: ,
  10. hiddenInput: true,
  11. inputCursor: '+',
  12. max: , //限制最大输入字符数
  13. min: , //限制最小输入字符数
  14. minWord: '', //提示语句
  15. imgUrl: '', //要上传的图片的url
  16. editText: '', //textarea中编辑的内容
  17. diarys: {},
  18. curPage:
  19. },
  20.  
  21. /**
  22. * 生命周期函数--监听页面加载
  23. */
  24. onLoad: function(options) {
  25.  
  26. },
  27.  
  28. //写日记
  29. writeDiary: function() {
  30. let tempCursor = ''
  31. if (this.data.inputCursor == '+') {
  32. tempCursor = '-'
  33. } else {
  34. tempCursor = '+'
  35. }
  36. this.setData({
  37. hiddenInput: !this.data.hiddenInput,
  38. inputCursor: tempCursor
  39. })
  40. //滚动视口,返回顶部
  41. wx.pageScrollTo({
  42. scrollTop: ,
  43. duration:
  44. })
  45. },
  46. /****限制字数与计算 */
  47. getValueLength: function(e) {
  48. let value = e.detail.value
  49. let len = parseInt(value.length)
  50. //最少字数限制
  51. if (len <= this.data.min)
  52. this.setData({
  53. minWord: "至少填写10个字哦~"
  54. })
  55. else if (len > this.data.min)
  56. this.setData({
  57. minWord: " "
  58. })
  59. //最多字数限制
  60. if (len > this.data.max) return;
  61. this.setData({
  62. currentWordNumber: len //当前字数
  63. })
  64. },
  65. formSubmit: function(e) {
  66. console.log('form发生了submit事件,携带数据为:', e.detail.value)
  67. let upDiaryContent = e.detail.value["diaryContent"]
  68. let upimgUrl = e.detail.value["img"]
  69. let len = parseInt(upDiaryContent.length)
  70. //最少字数限制
  71. if (len <= this.data.min) {
  72. this.setData({
  73. minWord: "至少填写10个字哦~"
  74. })
  75. return
  76. }
  77. wx.showLoading({
  78. title: '请等待',
  79. })
  80. //判断有无图片
  81. if (typeof upimgUrl == "undefined" || upimgUrl == null || upimgUrl == "") {
  82. //没有图片,直接上传文字
  83. const db = wx.cloud.database()
  84. db.collection('diarys').add({
  85. data: {
  86. content: upDiaryContent
  87. },
  88. success: res => {
  89. //无图,文字上传成功了
  90. this.reset()
  91. console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id)
  92. },
  93. fail: err => {
  94. wx.showToast({
  95. icon: 'none',
  96. title: '新增记录失败'
  97. })
  98. console.error('[数据库] [新增记录] 失败:', err)
  99. }
  100.  
  101. })
  102. } else { //有图片,则先上传图片
  103. const timestamp = new Date().getTime();
  104. const relCloudPath = 'diarys/' + timestamp + upimgUrl.match(/\.[^.]+?$/)[]
  105. console.log()
  106. console.log(upimgUrl)
  107. console.log(relCloudPath)
  108. wx.cloud.uploadFile({
  109. cloudPath: relCloudPath,
  110. filePath: upimgUrl,
  111. success: res => {
  112. console.log('[上传文件] 成功:', res)
  113. let imgFileID = res.fileID
  114. //再上传文字
  115. const db = wx.cloud.database()
  116. db.collection('diarys').add({
  117. data: {
  118. img: imgFileID,
  119. content: upDiaryContent
  120. },
  121. success: res => {
  122. //文字也上传成功了
  123. this.reset()
  124. console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id)
  125. },
  126. fail: err => {
  127. //文字上传失败
  128. wx.showToast({
  129. icon: 'none',
  130. title: '新增记录失败'
  131. })
  132. console.error('[数据库] [新增记录] 失败:', err)
  133. }
  134. })
  135. },
  136. fail: e => {
  137. console.error('[上传文件] 失败:', e)
  138. wx.showToast({
  139. icon: 'none',
  140. title: '上传失败',
  141. })
  142. }
  143. })
  144. }
  145. //图片和文字全部上传了。
  146. wx.hideLoading()
  147. },
  148. // 选择图片
  149. selPic: function() {
  150. var that = this
  151. wx.chooseImage({
  152. count: ,
  153. sizeType: ['compressed'],
  154. sourceType: ['album', 'camera'],
  155. success: function(res) {
  156.  
  157. wx.showLoading({
  158. title: '请等待',
  159. })
  160.  
  161. const imgfilePath = res.tempFilePaths[]
  162. that.setData({
  163. imgUrl: imgfilePath
  164. })
  165.  
  166. },
  167. fail: e => {
  168. this.setData({
  169. imgUrl: ''
  170. })
  171. //console.error(e)
  172. },
  173. complete: () => {
  174. wx.hideLoading()
  175. }
  176. })
  177. },
  178. //重置
  179. reset: function() {
  180. let tempCursor = ''
  181. if (this.data.inputCursor == '+') {
  182. tempCursor = '-'
  183. } else {
  184. tempCursor = '+'
  185. }
  186. this.setData({
  187. 'imgUrl': '',
  188. 'editText': '',
  189. 'hiddenInput': !this.data.hiddenInput,
  190. minWord: '',
  191. inputCursor: tempCursor
  192. })
  193. },
  194. // 查询当前用户的数据库集合,暂时没用
  195. onQuery: function(p) {
  196. const db = wx.cloud.database()
  197. db.collection('diarys').skip(p)
  198. .get()
  199. .then(res => {
  200. console.log(res.data)
  201. console.log(res.data[].img)
  202. })
  203. .catch(console.error)
  204. },
  205.  
  206. /**
  207. * 生命周期函数--监听页面初次渲染完成
  208. */
  209. onReady: function() {
  210. wx.getSystemInfo({
  211. success: res => {
  212. let h = res.windowHeight
  213. //取20条数据
  214. const db = wx.cloud.database()
  215. db.collection('diarys')
  216. .get()
  217. .then(res => {
  218. this.setData({
  219. mHeight: h,
  220. diarys: res.data
  221. })
  222. console.log(res.data)
  223. console.log(res.data[].img)
  224. })
  225. .catch(console.error)
  226. },
  227. })
  228.  
  229. },
  230.  
  231. /**
  232. * 生命周期函数--监听页面显示
  233. */
  234. onShow: function() {
  235.  
  236. },
  237.  
  238. /**
  239. * 生命周期函数--监听页面隐藏
  240. */
  241. onHide: function() {
  242.  
  243. },
  244.  
  245. /**
  246. * 生命周期函数--监听页面卸载
  247. */
  248. onUnload: function() {
  249.  
  250. },
  251.  
  252. /**
  253. * 页面相关事件处理函数--监听用户下拉动作
  254. */
  255. onPullDownRefresh: function() {
  256.  
  257. },
  258.  
  259. /**
  260. * 页面上拉触底事件的处理函数
  261. */
  262. onReachBottom: function() {
  263.  
  264. },
  265.  
  266. /**
  267. * 用户点击右上角分享
  268. */
  269. onShareAppMessage: function() {
  270.  
  271. }
  272. })

me.wxss

  1. /* pages/me/me.wxss */
  2. .currentWordNumber {
  3. height: 35px;
  4. line-height: 35px;
  5. font-size: 14px;
  6. float: right;
  7. margin-right: 15px;
  8. color: rgba(, , , );
  9. margin-bottom: 10px;
  10. }
  11. .minWord {
  12. color: rgb(, , );
  13. font-size: 14px;
  14. position: absolute;
  15. top: 30px;
  16. }
  17. .tips {
  18. width: %;
  19. margin-left: %;
  20. height: 45px;
  21. color: rgba(, , , );
  22. font-size: 14px;
  23. margin-top: 15px;
  24. text-align: left;
  25. font-family: PingFangSC-regular;
  26. }
  27. textarea {
  28. min-height: 500rpx;
  29. max-height: 500rpx;
  30. padding: 10rpx 10rpx;
  31. font-size: %;
  32. width: %;
  33. margin-left: %;
  34. margin-top: 15px;
  35. }
  36. .content {
  37. border-top: 1px solid rgb(, , );
  38. width: %;
  39. margin: auto;
  40. background-color: #ffff;
  41. }
  1.  

参考:授权 https://www.jianshu.com/p/480ff10bfb54

textarea https://blog.csdn.net/ChibiMarukoChan/article/details/88659746

...

微信小程序开发入门教程(四)---自己动手做个小程序的更多相关文章

  1. C#微信公众号开发系列教程四(接收普通消息)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  2. 微信小程序开发入门教程

    做任何程序开发要首先找到其官方文档,微信小程序目前还在邀请内测阶段,目前官方放出了部分开发文档,经过笔者一天的查看和尝试,感觉文档并不全面,但是通过这些文档已经能够看出其大概面貌了.闲话不多说,我们先 ...

  3. C#微信公众号开发入门教程

    首先打开开发文档: 微信公众号开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 一.创建测试账号 可以先申请一个开发者测试账号

  4. 微信小程序开发入门教程(二)---分析官方云开发例子中的一些功能

    接上一篇文章:https://www.cnblogs.com/pu369/p/11326538.html 1.官方云开发的例子中,点击获取 openid,对应代码在E:\wxDEV\helloyun\ ...

  5. 微信小程序开发入门教程(一)---hello world

    由于无法备案网站,前期做了个微信小程序(开发版)就搁置了,几乎忘了开发过程.现在重新梳理,做个记录. 一.最基本的小程序前端例子hello 1.下载安装  微信开发者工具  官网: https://d ...

  6. 微信小程序开发入门教程(三)---小程序云开发支付功能

    支付(shoukuan)功能真的很重要!由于我还没有商户号,以下代码未实际验证 1.服务端 进入云开发,新建云函数pay(应该也可以在开发者工具编写后上传) 编写后端代码index.js这里用到第三方 ...

  7. C#微信公众号开发系列教程六(被动回复与上传下载多媒体文件)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  8. C#微信公众号开发系列教程五(接收事件推送与消息排重)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  9. 微信小程序开发系列教程三:微信小程序的调试方法

    微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 这个教程的前两篇文章,介绍了如何用下图所示的微信开发者工具自动生成一个Hel ...

随机推荐

  1. C++继承种类

  2. MyBatis学习存档(3)——mapper.xml映射文件

    MyBatis 真正的强大在于映射语句,专注于SQL,功能强大,SQL映射的配置却是相当简单 所以我们来看看映射文件的具体结构 一.xml节点结构 mapper为根节点 - namespace命名空间 ...

  3. 植物大战僵尸:寻找召唤僵尸关键CALL

    实验目标:通过遍历寻找召唤僵尸的CALL,通过调用CALL出现自定义的僵尸,加速僵尸的出现. 僵尸CALL的遍历技巧: 我们可以通过僵尸出现在屏幕中的个数来遍历寻找僵尸出现的CALL 首先打开CE-& ...

  4. MySQL 聚合函数(一)聚合(组合)函数概述

    MySQL版本:5.7+ 本节介绍对值的集合进行操作的组合(聚合)函数.翻译自:Aggregate (GROUP BY) Function Descriptions 一.MySQL 5.7中的聚合函数 ...

  5. php对象转换为数组的部分代码

    function object_array($array){ if(is_object($array)){ $array = (array)$array; } if(is_array($array)) ...

  6. lamp :在Linux 下搭建apache、Mysql、php

    CentOS下搭建LAMP环境 LAMP: Linux + Apache + PHP + Mysql. 系统: CentOS 7,64位. CentOS安装 我选取了64位的CentOS 7这个Lin ...

  7. Python的global指令的作用

    Python的global指令的作用 学过其他常用编程语言的同学一定清楚,Python是一个语法非常宽容的语言.它是个变量的定义可以省略.直接赋值.根据赋值结果自动确定变量类型的弱类型语言. 但是这样 ...

  8. Dubbo相关的基础

    Dubbo是一款高性能轻量级的java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务注册与发现. Dubbo是阿里开源的一个项目,现在已经是Apache的顶级 ...

  9. python编程中常见错误

    python编程培训中常见错误最后,我想谈谈使用更多python函数(数据类型.函数.模块.类等)时可能遇到的问题.由于篇幅有限,我们试图将其简化,特别是一些高级概念.有关更多详细信息,请阅读学习py ...

  10. Nginx笔记一

      nginx: 为什么选择nginx: nginx是一个高性能的web和反向代理服务器. 作为web服务器:使用更少的资源,支持更多的并发连接,更高的效率,能够支持高达5w个并发连接数的相应, 作为 ...