总结下我的处女小程序。 小程序类似mvvm框架,和vue好像,这里主要以项目为主整理总结以供日后参考,可为初级小程序学习指南,主要包括以下: 云开发,数据库与云函数的使用 小程序生命周期 其他涉及音频,存储,动画,相关技巧
项目需求: 主要分四部分:多语言翻译,保存翻译历史,收藏功能,留言功能
项目截图及代码地址 云开发: 留言功能演示nodejs云函数后端开发 收藏功能演示小程序前端开发 ⑴. 使用云函数增删改查留言
首先需要初始化开发环境:
App ({
onLaunch : function () {
wx . cloud . init ({
env : 'test-263ef7' ,
traceUser : true ,
})
},
...
})
功能A:用户添加留言:
onSend () {
// 需要存入数据库的信息
let data = {
name : app . globalData . userInfo . name ,
avatar : app . globalData . userInfo . avatar ,
content : this . data . content ,
time : this . formateTime ( new Date ()),
};
// 判断
if ( ! data . name || ! data . content || ! data . avatar ) {
wx . showToast ({
title : '留言失败' ,
})
return ;
}
// 添加留言
wx . cloud . callFunction ({
// 云函数名称
name : "addMessages" ,
// 传入的数据
data ,
// 调用成功
success : res => {
// res 包含该条留言的所有信息,包括随机生成_id
},
fail () {
console . log ( "云函数 addMessages 调用失败" )
}
})
},
保存示意图:
新建nodejs云函数代码
// index.js
// 云函数入口文件
const cloud = require ( 'wx-server-sdk' )
cloud . init ();
// 云函数里面也需要指定环境
const db = cloud . database ({
env : "test-263ef7"
})
// 云函数入口函数
exports . main = async ( event , context ) => {
// 保存
let res = await db . collection ( "message-trans" ). add ({
data : {
name : event . name ,
content : event . content ,
time : event . time ,
avatar : event . avatar
},
})
let id = res . _id ;
// 返回该条留言的所有信息
return db . collection ( "message-trans" ). doc ( id ). get ()
}
打印event,context
功能B: 用户获取所有留言
onLoad : function () {
wx . cloud . callFunction ({
name : "getAllMessages" ,
success : res => {
let mes = res . result . data ;
mes = mes . reverse ();
this . setData ({
messages : mes
});
...
},
fail : () => {
console . log ( "云函数 getAllMessages 调用失败" )
}
});
},
新增getAllMessages 云函数
exports . main = async ( event , context ) => {
return await db . collection ( "message-trans" ). get ();
}
功能C: 删除留言
// 每个 view 设置data的内容:
data - name = "{{message.name}}"
data - time = "{{message.time}}"
data - index = "{{index}}"
data - content = "{{message.content}}"
// js
onDeleteMes ( e ) {
let time = e . currentTarget . dataset . time ;
let index = e . currentTarget . dataset . index ;
wx . showModal ({
title : '提示' ,
content : '是否删除该留言' ,
success : ( res ) => {
if ( res . confirm ) {
wx . cloud . callFunction ({
name : "deleteMessage" ,
// 根据 时间和用户名来确认是 当前用户的留言,,只能删除自己的留言
data : {
time ,
name : app . globalData . userInfo . name
},
success : res => {
...
},
fail () {
console . log ( "云函数 deletemessgae调用失败" )
}
})
} else if ( res . cancel ) {
console . log ( '用户点击取消' )
}
}
})
新建deleteMessage云函数
exports . main = async ( event , context ) => {
return db . collection ( "message-trans" ). where ({
// 查询条件
time : event . time ,
name : event . name
}). remove ();
}
PS : 如果两名昵称相同的人在同一时间留言 , 会把两个人的都删除 , 所以可增加查询条件 : 比如name , time , content , avatar都相同 ,
注意:
每次修改云函数需要重新上传部署
⑵. 前端增删改查收藏功能
"/utils/favorite.js"
const db = wx . cloud . database ();
const app = getApp ();
let Favorite = {
name : "favorite-trans" ,
openid : app . globalData . userid ,
// 收藏
like ( data ) {
return new Promise (( resolve , reject ) => {
db . collection ( this . name ). add ({
data ,
success : ( res ) => {
resolve ( res )
},
fail () {
console . log ( "收藏失败" )
}
})
})
},
// 取消收藏
unLike ( data ) {
return new Promise (( resolve , reject ) => {
if ( data . id ){
db . collection ( "favorite-trans" ). doc ( data . id ). remove ();
} else {
db . collection ( this . name ). where ({
_openid : this . openid ,
query : data . query ,
result : data . result
}). get ({
success : ( res ) => {
let id = res . data [ 0 ]. _id ;
db . collection ( "favorite-trans" ). doc ( id ). remove ();
resolve ( res )
}
})
}
})
},
// 获取所有收藏
//云函数可以获取100条数据,普通方式只能获取20条, 所以这里依然使用云函数获取收藏列表
getAll () {
return new Promise (( resolve , reject ) => {
wx . cloud . callFunction ({
name : "getAllFavorites" ,
success : res => {
let fa = res . result . data ;
fa = fa . reverse ();
resolve ( fa )
},
fail : () => {
console . log ( "云函数 getAllFavorites 调用失败" )
}
});
})
},
// 检查是否收藏
check ( data ) {
return new Promise (( resolve , reject ) => {
db . collection ( this . name ). where ({
_openid : this . openid ,
query : data . query ,
result : data . result
}). get ({
success : ( res ) => {
let flag = res . data . length ? true : false ;
resolve ( flag )
},
fail () {
console . log ( "检查是否收藏失败" )
}
})
})
}
}
export default Favorite ;
云函数 getAllFavorites
页面切换与小程序生命周期 (1). 页面切换的几种方式:
页面链接:<navigator> tabBar wx.navigateTo wx.switchTab wx.reLaunch wx.navigateBack (2). 生命周期回调函数
onLoad >> 监听页面加载,只触发一次,参数中获取打开当前页面路径中的参数
示例:
// history 进入 index
// history
wx . reLaunch ({
url : `../index/index?query= ${ data . query } &result= ${ data . result } ` ,
})
// index
onLoad ( options ) {
if ( options . query && options . result ) {...}
}
onShow >> 监听页面显示, 每次进入该页面都会触发,
如果每次进入页面都需要重新渲染
onShow (){
this . onLoad ();
}
onReady >> 页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。
对界面内容进行设置的 API, 需要在onReady 之后
onHide >> 页面隐藏/切入后台时触发
示例:离开页面时保存最终状态并存入历史
onHide () {
...
},
onUnload () {
this . onHide ();
},
onUnload >> 页面卸载时触发,如redirectTo
或navigateBack
到其他页面时。
本地存储 wx . setStorageSync ( string key , any data )
wx . getStorageSync ( string key )
可以存入任何数据类型
音频 示例:播放单词发音
onGetcurVoice () {
const audio = wx . createInnerAudioContext ()
audio . src = this . data . allTranistion . tSpeakUrl ;
audio . play ();
audio . onPlay (() => {
console . log ( '开始播放' )
this . setData ({
isSayingCur : true
})
})
audio . onEnded (() => {
console . log ( '播放结束' )
this . setData ({
isSayingCur : false
})
})
audio . onError (( res ) => {
console . log ( res )
})
}
剪切板 示例:复制翻译结果
onCopy () {
let flag = 1 ;
if ( ! this . data . query ) {
wx . showToast ({
title : '啥都没有' ,
})
flag = 0
}
if ( flag ) {
wx . setClipboardData ({
data : String ( this . data . result ),
success : res => {
wx . showToast ({
title : '复制成功' ,
})
}
})
}
},
动画 示例:
onChangeOrigin () {
[ app . globalData . curLang , app . globalData . prevLang ] = [ app . globalData . prevLang , app . globalData . curLang ];
wx . setStorageSync ( 'trans_prevLang' , app . globalData . prevLang );
wx . setStorageSync ( 'trans_curLang' , app . globalData . curLang );
const animation1 = wx . createAnimation ({
duration : 1000 ,
timingFunction : 'ease' ,
});
const animation2 = wx . createAnimation ({
duration : 1000 ,
timingFunction : 'ease' ,
})
animation1 . translateX ( 65 ). step ();
animation2 . translateX ( - 65 ). step ();
this . setData ({
animationPrev : animation1 . export (),
animationCur : animation2 . export (),
});
setTimeout (() => {
animation1 . translateX ( 0 ). step ();
animation2 . translateX ( 0 ). step ();
this . setData ({
animationPrev : animation1 . export (),
animationCur : animation2 . export (),
});
this . setData ({
curLang : app . globalData . curLang ,
prevLang : app . globalData . prevLang
});
}, 500 );
}
其他
1.wx:if 与 hidden 的取舍
因为 wx:if
之中的模板也可能包含数据绑定,所以当 wx:if
的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。
同时 wx:if
也是惰性的 ,如果在初始渲染条件为 false
,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。
相比之下,hidden
就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
一般来说,wx:if
有更高的切换消耗而 hidden
有更高的初始渲染消耗。,
如果需要频繁切换的情景下,用 hidden
更好 在运行时条件不大可能改变则 wx:if
较好。 2.动态class
< view class = "aaa {{showFlag ? " bbb " : ""}}" ></ view >
3. catchtap 阻止冒泡
4.使用云函数保存时不会在数据库中存储 openid ,普通方法会。
小程序码: Appendix:
小程序官方教程
相对于代码,最难的是有明确的业务需求,有可见的项目图纸,论产品经理与ui设计师的重要性[泪奔],用户体验至上。
护眼美图: