小程序可以视为只能用微信打开和浏览的网站,小程序页面本质上就是网页
项目体积不能超过20MB
微信 App 的功能(比如拍照、扫描、支付等等),小程序大部分都能使用
标签表示一个区块,用于跟其他区块分隔, 类似 HTML的
标签
表示一段行内文本,类似于 HTML的标签
{
"pages": [
"pages/home/home"
],
"window": {
"navigationBarBackgroundColor": "#ff0000", //导航栏的颜色,默认黑色
"navigationBarTextStyle": "white", //导航栏的文字颜色,只支持黑白,默认白
"navigationBarTitleText": "小程序 Demo" //导航栏的文字,默认为空
}
}
全局样式文件:顶层的app.wxss文件,里面采用 CSS 语法设置页面样式
局部样式文件:每个page对应一个单独的wxss文件
推荐布局方式:Flex
推荐长度单位:rpx【小程序自创响应式单位,任何设备宽度都是750rpx】
推荐的UI框架:WeUI【官方封装的UI框架】https://weui.io/
源码:https://github.com/Tencent/weui-wxss/
在dist/style/weui.wxss文件,将源码全部复制到你的app.wxss文件的头部
<view>
<button class="weui-btn weui-btn_primary">
主操作
button>
<button class="weui-btn weui-btn_primary weui-btn_loading">
<i class="weui-loading">i>正在加载
button>
<button class="weui-btn weui-btn_primary weui-btn_disabled">
禁止点击
button>
view>
<image src="https://picsum.photos/200">image>
<swiper
indicator-dots="{{true}}" 是否显示轮播点
autoplay="{{true}}" 是否自动播放
style="width: 750rpx;">
<swiper-item>
<image src="https://picsum.photos/200">image>
swiper-item>
<swiper-item>
<image src="https://picsum.photos/250">image>
swiper-item>
<swiper-item>
<image src="https://picsum.photos/300">image>
swiper-item>
swiper>
小程序的数据绑定类似VUE,也遵循MVVM设计模式,文本框直接用{{}}
在JS中定义数据
Page({
data: {
name: '张三'
}
});
在WXML中使用数据
<view>
<input value='{{name}}'/>
<text> {{name}}text>
view>
Page({
data: {
items: ['事项 A', '事项 B', '事项 C']
}
});
<view>
<text class="title" wx:for="{{items}}">
{{index}}、 {{item}}
text>
view>
<view>
<input model:value='{{name}}'/>
view>
在根路径下的app.js中的gloablData对象里配置全局共享数据
App({
globalData: {
userInfo: {
name:'小王'
}
}
})
在任意一个页面中获取共享数据
Page({
data: {
name: getApp().globalData.userInfo.name
}
});
tap:触摸后马上离开。
longpress:触摸后,超过 350ms 再离开。如果指定了该事件的回调函数并触发了该事件,tap事件将不被触发。
touchstart:触摸开始。
touchmove:触摸后移动。
touchcancel:触摸动作被打断,如来电提醒,弹窗等。
touchend:触摸结束。
同一个事件在同一个元素上面其实会触发两次:捕获阶段一次,冒泡阶段一次
capture-bind:捕获阶段触发。
capture-catch:捕获阶段触发,不再向下传播,并取消随后的冒泡阶段。
bind:冒泡阶段触发。
catch:冒泡阶段触发,并取消事件进一步向上冒泡
通常使用的是:bind+tap的组合
<button bindtap="buttonHandler">点击button>
buttonHandler(){
this.data.name; //获取name属性
this.setData({
name:'xxx' //更新name属性
})
}
跳转到应用内非 tabBar 的页面路径,保留历史记录(navigate:导航)
wx.navigateTo({
url: '/second/second?key1=value1&key2=value2'
});
返回上一页面或多级页面
wx.navigateBack({
delta: 2
})
跳转到 tabBar 页面(在tabBar配置的页面,要用switchTab跳转)(switch:开关)
wx.switchTab({
url: '/index'
})
跳转到应用内非 tabBar 的页面路径,不保留历史记录(redirect:重定向)
wx.redirectTo({
url: 'test?id=1'
})
接收参数:(load:载入)
onLoad(options) {
console.log('参数:',options);
}
choose:选择 source:从某地获得 type:类型
chooseAvatar() {
var abc = this;
wx.chooseImage({
count: 1, //最多选择几张照片
sizeType: ['compressed', 'original'], // compressed:压缩 original:原始
sourceType: ['album', 'camera'], // album:相册 camera:相机
success(res) {
// 获得图片临时路径
console.log(res.tempFilePaths[0]);
getApp().globalData.userInfo.avatar = res.tempFilePaths[0]
abc.setData({
avatar: res.tempFilePaths[0]
})
}
})
},
wx.showToast({
title: '操作完成',
duration: 700
});
const that = this;
wx.showModal({
title: '操作确认',
content: '你确认要修改吗?',
success (res) {
if (res.confirm) {
wx.showToast({
title: '操作完成',
duration: 700
});
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
同步:
wx.setStorageSync(key,value)
wx.getStorageSync(key)
异步:
wx.setStorage({ key:"key", data:"value"})
wx.getStorage({ key: 'key',success (res) {
console.log(res.data)
}
})
<button bindtap='getUserProfile'>获取头像昵称button>
getUserProfile(e){
getUserProfile({
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success(res){
console.log(res) // 拿到用户信息
}
})
}
onLaunch() | 小程序启动(执行一次)(Launch:启动) |
---|---|
onShow() | 小程序显示(show:显示) |
onHide() | 小程序隐藏(hide:隐藏) |
onError() | 小程序报错(error:错误) |
onLoad() | 加载完成(执行一次)(负责接收页面参数)(load:加载) |
---|---|
onShow() | 当前页面显示(show:显示) |
onHide() | 当前页面隐藏(hide:显示) |
onReady() | 渲染完成(类似vue的mounted)(ready:准备改了) |
onUnlode() | 当前页面卸载(unload:卸载) |
{
"usingComponents": {
"shop-list":"/pages/shopList/shopList"
}
}
<shop-list>shop-list>
默认情况下,自定义组件的样式只受到自定义组件 wxss 的影响。除非以下两种情况:
app.wxss
或页面的 wxss
中使用了标签名选择器(或一些其他特殊选择器)来直接指定样式,这些选择器会影响到页面和全部组件。通常情况下这是不推荐的做法。styleIsolation
。Component({
options: {
styleIsolation: 'isolated'
}
})
在开发者工具中预览效果
styleIsolation
选项从基础库版本 2.6.5 开始支持。它支持以下取值:
isolated
表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值);apply-shared
表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;shared
表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-shared
或 shared
的自定义组件。(这个选项在插件中不可用。)使用后两者时,请务必注意组件间样式的相互影响。
如果这个 Component 构造器用于构造页面 ,则默认值为 shared
,且还有以下几个额外的样式隔离选项可用:
page-isolated
表示在这个页面禁用 app.wxss ,同时,页面的 wxss 不会影响到其他自定义组件;page-apply-shared
表示在这个页面禁用 app.wxss ,同时,页面 wxss 样式不会影响到其他自定义组件,但设为 shared
的自定义组件会影响到页面;page-shared
表示在这个页面禁用 app.wxss ,同时,页面 wxss 样式会影响到其他设为 apply-shared
或 shared
的自定义组件,也会受到设为 shared
的自定义组件的影响。从小程序基础库版本 2.10.1 开始,也可以在页面或自定义组件的 json 文件中配置 styleIsolation
(这样就不需在 js 文件的 options
中再配置)。例如:
{
"styleIsolation": "isolated"
}
此外,小程序基础库版本 2.2.3 以上支持 addGlobalClass
选项,即在 Component
的 options
中设置 addGlobalClass: true
。 这个选项等价于设置 styleIsolation: apply-shared
,但设置了 styleIsolation
选项后这个选项会失效。
代码示例:
在开发者工具中预览效果
/* 组件 custom-component.js */
Component({
options: {
addGlobalClass: true,
}
})
<!-- 组件 custom-component.wxml -->
<text class="red-text">这段文本的颜色由 `app.wxss` 和页面 `wxss` 中的样式定义来决定</text>
/* app.wxss */
.red-text {
color: red;
}
父组件:
<goos-list list="{{xq}}">goos-list>
父组件:
{
"usingComponents": {
"goos-list": "/pages/goosList/goosList"
}
}
父组件:
xq:[······]
子组件:
子组件:
proprties:{
list:{
type:Array,
value:[]
}
}
父组件:
<goos-list bindClick='play'>goos-list>
父组件:
{
"usingComponents": {
"goos-list": "/pages/goosList/goosList"
}
}
父组件:
play(value){
console.log('子传父:' + value) // value为子组件传回的值
}
子组件:
<image src='' bindtap='play_son'>image>
子组件:
play_son(){
this.triggerEvent('bindClick')
}
created
created(){
//组件实例刚刚被创建好时(此时还不能调用 setData)
}
attached
attached(){
//组件完全初始化完毕(绝大多数初始化工作在此执行)
}
detached
detached(){
//组件实例被从页面节点树移除时
}
云开发代替了传统的后台服务,前端人员容易上手
AppID不能使用测试号
开通云开发服务,获取环境名称和环境 ID
给cloudfunctions 文件夹名设置当前的环境名称
指定小程序的云开发环境:miniprogram 里的 app.js
wx.cloud.init({
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看(云开发=> 设置 => 环境ID)
env: 'my-env-id', //
traceUser: true,
})
---------------------------------------
//app.js文件
App({
onLaunch: function () {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
console.log('--wx.cloud.init--')
wx.cloud.init({
env: 'cloud1-8ghbh19oafb43f5c',
traceUser: true,
})
}
this.globalData = {}
}
})
鼠标放在cloudfunctions文件夹上右键点击:新建Node.js云函数 例如:login
打开index.js文件会看到默认生成的代码,它会直接获取当前上下文,并返回我们所需的openid和一些其他信息
右键login文件夹->在内建终端打开
安装依赖:npm install
右键login文件夹->开启云函数本地调试
// 后端的index.js文件
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
// evevt为返回值(使用他进行计算等操作)
return {
event,
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
}
}
在调试面板最右侧请求方式:手动触发
点击绿色按钮:调用
点击Console查看结果
如果云函数调试成功,说明代码没有问题,点击login右键->上传并部署所有文件,这样做了才能在小程序端调用到
在miniprogram中任意创建一个页面,例如:main
在main/main.js中的onLoad事件中获取环境ID,保存到data中,可以从envList.js文件中得到
用下面的代码调用云函数
wx.cloud.callFunction({
name: 'login',//云函数名称
config: {
env: 'xx' //环境ID
},
data: {'自己的XX参数'}
})
——————————————————————————————————————
const {envList} = require('../../envList')
wx.cloud.callFunction({
name:'login', //调用的云函数名称
config:{
env:envList[0].envId
},
data:{}
}).then(res=>{
console.log(res)
})
使用wx.chooseImage获取手机图片
使用wx.cloud.uploadFile将文件上传到云存储中
在云开发面板->云存储可以看到上传的文件信息
代码实例:
wx.chooseImage({count: 1,//选择图片最大数量
sizeType:['compressed','original'],//图片质量
sourceType: ['album', 'camera'],//图片来源(相册,相机)
success (res) {
//拿到照片
const filePath = res.tempFilePaths[0]
var pointIndex = filePath.lastIndexOf('.')
var extname = filePath.substring(pointIndex);//图片后缀名
//更名
const cloudPath = Date.now() + extname;//利用云存储将照片保存到云端
wx.cloud.uploadFile({
filePath,
cloudPath,
success:function(res){
//将云端的图片路径赋值给当前页面的头像
that.setData({
avatar:res.fileID
})
}
})
}
})
---------------------------------------------------------------------
wx.chooseImage({
count: 1,//选择图片最大数量
sizeType:['compressed','original'],//图片质量
sourceType: ['album', 'camera'],//图片来源(相册,相机)
success (res) {
//拿到照片
const filePath = res.tempFilePaths[0]
var pointIndex = filePath.lastIndexOf('.')
var extname = filePath.substring(pointIndex);//图片后缀名
//更名
const cloudPath = Date.now() + extname;
//利用云存储将照片保存到云端
wx.cloud.uploadFile({
filePath,
cloudPath,
success:function(res){
//将云端的图片路径赋值给当前页面的头像
that.setData({
avatar:res.fileID
})
}
})
}
})
在菜单“云开发”中找到:数据库->新建一个集合->存几条数据
新建一个云函数
// 云函数入口文件
const cloud = require('wx-server-sdk')//配置环境
IDcloud.init({env:cloud.DYNAMIC_CURRENT_ENV})//获取数据库实例
let db = cloud.database()// 云函数入口函数
exports.main = async (event, context) => {
//数据查询
return await db.collection('zhihu_daily').get()
}
------------------------------------------------------------
// 云函数入口文件
const cloud = require('wx-server-sdk')
//配置环境ID
cloud.init({
env:cloud.DYNAMIC_CURRENT_ENV
})
//获取数据库实例
let db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
//数据查询(上面的是main.js自动生成的)
return await db.collection('my_SQL').doc(event.id).remove()
}
安装依赖+本地调试+上传
在本地页面调用该云函数,获得结果
wx.cloud.callFunction({
name:'zhihu_daily',
config:{
env:envList[0].envId
},
data:{}
}).then(res=>{
console.log(res.result.data)
})
------------------------------------------------------------
//调用云函数查询数据
wx.cloud.callFunction({
name:'zhihu_daily',
config:{
env:envList[0].envId
},
data:{}
}).then(res=>{
console.log(res.result.data)
that.setData({
items:res.result.data
})
})
// 后端main.js文件
// 云函数入口文件
const cloud = require('wx-server-sdk')
// 配置环境ID
cloud.init({
env:cloud.DYNAMIC_CURRENT_ENV
})
// 获得数据库实例
let db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
return await db.collection('my_SQL').get()
}
----------------------------------------------------------
前端:.js文件
// 删除
async rem(event){
// 通过data-id的方式获得对应数据库的id号
console.log(event.target.dataset.id);
let id = event.target.dataset.id
await wx.cloud.callFunction({
name:'my_SQL',
config:{
env:envList[0].envId,
},
data:{
id
}
})
},
----------------------------------------------------------
// 后端另一个执行删除操作的云函数的main.js的文件
// 云函数入口函数
exports.main = async (event, context) => {
return await db.collection('数据库名').doc(event.id).remove()
}
删除:db.collection(‘表名’).doc(‘_id值’).remove()
删除必须要有条件,doc()里面传入数据的id可以查出一条唯一数据来
更新:db.collection(‘表名’).doc(‘_id值’).update({data:{更新条件}})
添加:db.collection(‘表名’).add({JSON形式的数据字段})
查询条数:db.collection(‘表名’).count()
条件查询:db.collection(‘表名’).where({查询条件}).get()
分页查询:db.collection(‘表名’).skip(跳过数量).limit(条数).get()
单条查询:db.collection(‘表名’).doc(id值).get()
一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序。
新建项目->uni-app项目
在manifest.json中配置申请的AppID
静态资源只能存放于static文件夹中,访问时以 / 开头
每个平台有自己的一些特性,因此会存在一些无法跨平台的情况
条件编译写法 | 说明 |
---|---|
#ifdef APP-PLUS(代码)#endif | 只在app中出现的代码 |
#ifndef H5(代码)#endif | 除了H5平台,其他平台均出现的代码 |
#ifdef H5 || MP-WEIXIN(代码)#endif | 只在 H5平台 或 微信小程序 中出现的代码 |
只在App中可以看到:{{title}}
再在微信小程序在可以看到:{{title}}
只在H5中可以看到:{{title}}
写法:
平台特有的组件
/* #ifdef %PLATFORM% */
平台特有样式
/* #endif */
// #ifdef %PLATFORM%
平台特有的API实现
// #endif
基本流程和微信一样
获取code
const [loginErr, loginRes] = await uni.login({
provider: 'weixin'
})
//获取微信code,传递后端
loginRes.code
-------------------------------------------------------------------
uni.login({
provider:'微信'
}).then(res=>{
console.log(res)
})
结果:
(2) [null, {…}]
0: null
1: {errMsg: "login:ok", code: "07180oFa1b6e3C021nHa1X8Z0p080oF4"} // 拿到code
length: 2
nv_length: 2
__proto__: Array(0)
拿到code传递后后端,后端根据code+app id + app Secret 请求微信服务器,获取open id
// 获取用户信息
uni.getUserProfile({
desc:'微信',
success: (res) => {
this.aaa= res.userInfo.nickName // userInfo:用户信息
console.log(res)
}
})
onLauch(){
//当uni-app初始化完成时触发(全局触发一次)
}
onShow(){
//当uni-app启动,或从后台进入前台显示
}
onHide(){
//当uni-app从前台进入后台
}
onError(){
//当uni-app报错时触发
}
onLoad(option){
//页面加载完成事件,并且可以从option接收参数
}
onShow(){
//监听页面显示,每次出现当前页面时都触发
}
onReady(){
//监听页面初次渲染完成
}
onHide(){
//监听页面隐藏
}
onUnload(){
//监听页面卸载
}
uni-app内置了vuex,只需创建store/index.js,并且引入即可
//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {},
mutations: {},
actions: {}
})
export default store
//main.js
import Vue from 'vue'
import store from './store'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
store,
...App
}).$mount()
和小程序的语法基本一致
uni.request({
url: 'https://www.example.com/request',
data: {
text: 'uni.request'
},
method:'GET',
header: {
'custom-header': 'hello'
},
success: (res) => {
console.log(res.data);
},
fail:(err) => {}
});
manifest.json的源码视图
"h5" : {
"devServer" : {
"port" : 8080,
"disableHostCheck" : true,
"proxy" : {
"/" : {
"target" : "http://192.168.0.101:8081/",
"changeOrigin" : true,
"secure" : false
}
}
}
}
<map style="width: 500px; height: 300px;" :markers="markers"
:latitude="latitude" :longitude="longitude">
map>
data(){
return {
title: 'map',
latitude: 39.909,//纬度
longitude: 116.39742,//经度
markers:[{id:1,latitude:xxx,longitude:xxx,iconPath:’xx.jpg’,width:20,height:20}]//在地图上的坐标点
}
}
uni.getLocation({
type: 'gcj02', //wgs84 gps 坐标;gcj02 返回国测局坐标
success: function (res) {
console.log('当前位置的经度:' , res.longitude);
console.log('当前位置的纬度:' , res.latitude);
console.log('详细的地址信息:' , res.address);//仅app支持
}
});
uniapp内置的getLocation函数,仅在APP端可以获取中文位置信息?
如果希望在小程序端也拿到中文信息,则可以使用腾讯地图API
baidu搜索:腾讯地图开放平台
开发文档:微信小程序JavaScript SDK
申请开发者密钥(创建应用,添加key,填写APPID)
下载微信小程序SDK(拿到js文件,放到项目目录中)
安全域名设置:添加
https://apis.map.qq.com添加为合法域名
代码实现:在当前地区搜索酒店的信息和坐标
import QQMapWX from ‘./qqmap-ws-jssdk.min.js’
onLoad(){
//实例化
this.qqmapwx = new QQMapWX({
key:’申请的地图KEY’
})
this.qqmapwx.search({
keyword:’酒店’,
success:function(res){}
})
}
uni.navigateToMiniProgram(OBJECT)
uni.navigateToMiniProgram({
appId: '',
path: 'pages/index/index?id=123',
extraData: {
'data1': 'test'
},
success(res) {
// 打开成功
}
})
只有当另一个小程序跳转到当前小程序时才会能调用成功。
uni.navigateBackMiniProgram(OBJECT)
uni.navigateBackMiniProgram({
extraData: {
'data1': 'test'
},
success(res) {
// 返回成功
}
})
uni.checkSession({
success: (res) => {
if (res.errMsg == 'checkSession:ok') {
console.log(res);
console.log('登录暂未过期');
console.log(uni.getStorageSync('openId'));
}
},
fail: (err) => {
console.log(err, '已过期')
//过期的话调用接口
uni.showModal({
cancelText: '取消',
confirmText: '确定',
title: '登录已过期,请重新登录',
success: (res) => {
if (res.confirm) {
uni.showLoading({
mask: true,
title: '登录中...'
})
uni.login({
provider: 'weixin',
success: (res) => {
console.log(res);
}
})
}
}
})
}
})