mini小程序入坑说明
开发者ID - 小程序 - 开发-开发管理 - 开发设置
代码上传 - 小程序 - 管理-版本管理-查看提交的信息
小程序介绍:
当微信中的 WebView 逐渐成为移动 Web 的一个重要入口时,微信就有相关的 JS API 【微信打开html网页】
微信小程序,2016年末推出,2017年初第一批小程序正式上线
SDK software-Development-Kit 软件开发工具包
小程序与普通网页开发的区别
小程序的主要开发语言是 JavaScript
网页开发渲染线程和脚本线程是互斥的, 而在小程序中,二者是分开的分别运行在不同的线程中。
网页开发可使用DOM API,小程序开发缺少相关的DOM API和BOM API
网页开发主要考虑浏览器兼容,小程序开发主要考虑的是安卓与iOS两大操作系统
第一个小程序
?问你开发工具 : 微信开发者工具
打开微信开发者工具 - 微信扫一下 - 注册的账号登录 - 项目名字 - 项目目录 - AppleID - 不使用云服务 - js | ts - 基础模板 -
下载微信开发者工具 并安装,使用微信扫码登录工具,创建小程序项目。
创建小程序应用时,选择填写自己的 AppID,先不使用云开发,选择最基础的模板即可。
可先认识一下开发者工具的界面结构
四类文件
每个文件夹下的四类文件名称需要一致
.json 后缀的 JSON 配置文件
.wxml 后缀的 WXML 模板文件
.wxss 后缀的 WXSS 样式文件
.js 后缀的 JS 脚本逻辑文件
JSON配置
程序中,后缀名为 *.json 的文件是静态配置文件
app.json
小程序的全局配置文件
pages字段:是小程序中所有页面路径(routes)配置,是数组结构。默认情况下,将数组的第一个元素表示的路径作为小程序应用的”首页“
默认将pages数组中第一项作为小程序首页,否则可设置 entryPagePath
window字段:小程序应用窗口的全局配置。 所有页面的顶部背景颜色,文字颜色定义等
enablePullDownRefresh:true, // 每个页面都允许下拉刷新功能
1
小程序最大为20M,每个分包2M
tabbar字段:| 自定义
2-5项tab,初始图标,选中激活图标,颜色
图表大小推荐 81*81
sitemap.json
配置是否允许微信对小程序页面进行索引
页面局部设置:navigationBarTitleText:‘页面标题’
WXML
充当的是 HTML 文件
WXML 中标签于 HTML 标签名字不一样,在标签中可使用类似 wx:if 的属性,{{ }} 插值的语法,
WXSS
充当的是css文件
书写同css规则,新增了 rpx 单位(响应式的单位),避免的换算困难(rem换算)。app.wxss文件中,提供了全局样式文件的处理
可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像
JS文件
主要负责交互逻辑
app.js
app.js 文件负责的是注册小程序应用
调用 App() 函数来注册小程序应用:
App({ /** * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次) */ onLaunch: function () { }, /** * 当小程序启动,或从后台进入前台显示,会触发 onShow */ onShow: function (options) { }, /** * 当小程序从前台进入后台,会触发 onHide */ onHide: function () { }, /** * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息 */ onError: function (msg) { } })
onLaunch()、onShow()、onHide() 是小程序应用的生命周期钩子函数
页面 js
注册页面,调用 Page() 函数来注册页面:
Page({ /** * 页面的初始数据,类似于 react class 组件中的 state。 * 要修改 data 中的数据,调用 setData() 方法来修改 */ data: { }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { } })
taotao-原生小程序开发
小程序开发工具坑很多-慢慢尝试-重开
构建页面结构:首页/购物车/分类/登录…
app.json 配置 pages字段 、 window全局窗口配置、tabbat/list属性配置、
/images/tab-bar-icon/imgs.png存放图标渲染
navigationStyle:custom //自定义导航条样式 onReachBottomDistance:number //上拉处理距离底部高度 subpackage:object[] //分包 perimission:object //权限获取
布局-wxml文件
view标签 =》 div 视图容器
swiper滑块视图容器 swiper-item轮播每一项
scroll-view滚动视图
分类滚动视图
<scroll-view scroll-x = "true" //字符串 scroll-x = "{{ true }}" //布尔值 /> <!-- 列表渲染 item固定名称--> <text wx:for= “{{ cat }}” wx:key= "id" > <!--item代表名称 index代表索引--> {{item}} 分类名称 {{index}} </text>
列表渲染:绑定 key 提高性能
换行解决 white-space
发网络请求
index.js
data:{ //初始数据 cat:[ {} ] }
index.wxss
-写样式代码
网络请求
API: wx.request( object )
wx.request({ url:'', success:res=>{ //数据处理-状态为200,处理返回数据 if(res.statusCode===200){ const { code,data } = res.data if(code ===200 ){ //调用setData修改数据 this.setData( cat:data.list ) } } }, fail:err=>{}, })
小程序跨域-详情-本地设置-不校验本地合法域名勾选
项目上线后,只能发https请求
多次请求繁琐,实现 axios 封装
wx.request 不支持promise写法
utils/request.js 二次封装
commonJS的规范 – module.exports导出 require()
/** * wx.request() 方法的二次封装处理 */ const baseURL = 'http://quanzhan.site:3000' const request = ({url, data, header = {}, method = 'GET'} = {}) => { // 新 new Promise() 创建的 Promise 对象的状态是 pending 待定状态 return new Promise((resolve, reject) => { wx.request({ url: baseURL + url, // 在访问接口前拼接统一的 baseURL data, // 请求发送给后端的数据 header: { // 请求头 ...header, 'X-Token': 'token string.............', // 携带 token 认证字段 }, timeout: 5000, // 请求超时时间 method, // 请求方法,默认为 GET success: res => { // 请求成功的回调函数 if (res.statusCode === 200) { // HTTP状态码为 200 表示 OK // res.data 中保存的是后端向前端返回的数据 // 通常后端与前端交互时有统一的规范,比如返回一个对象,有 code 与 data、message 属性。 // 当前接口规范中,code 为 200 表示后端向前端返回成功的数据。 // 返回的数据在 data 属性中。 const {code, data} = res.data if (code === 200) { resolve(data) // 将 Promise 的状态修改为 fulfilled 成功状态,并携带成功的数据 return } } // 如果 HTTP 状态码或后端返回的 code 表示有误时,将 // Promise 状态修改为 rejected 失败状态,携带失败原因。 const error = new Error('接口访问有误') reject(error) }, fail: err => { // 请求失败 // 将 Promise 状态标记为失败状态 reject(err) }, }) }) } // 利用 CommonJS 规范中的 module.exports 导出当前文件中定义的 request 方法 module.exports = request
轮播图swiper
<swiper indicator-dots //显示面板指示点 autoplay //自动播放 duration //500m内完成滑动 ... > ------------------------------------------------ <!-- 轮播图 --> <swiper indicator-dots autoplay > <block wx:for="{{ banners }}" wx:key="id"> <swiper-item> <image src="{{item.image}}" style="width:100%;height:100%"></image> </swiper-item> </block> </swiper>
block标签类似<></>
block` 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性
image标签默认宽高 320*240
if(this.data.isEnd){ console.log('到底了'); return } console.log('...'); //触底发送网络请求 let data = await request({ url:'/api/tab/1/feeds?start=' + this.data.nextIndex }) console.log('触底:',data); this.setData({ //!this.date.list productList:this.data.productList.concat(data.list), isEnd:data.isEnd, nextIndex:data.nextIndex, })
if vs hidden
wx:if vs hidden
因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。
同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。
相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好
<view wx:if="{{ !isEnd }}">加载中...</view> <view wx:else="{{ isEnd }}">我是有底线的!!</view>
点击商品详情跳转-
navigator组件 <navigator to="/...."> // 跳转到其他小程序 - 需要app-id配置 // 跳转到当前小程序其他页面 //图像绑定点击事件 300ms之内为短按 tap 长按longpress bindtap = "handleBing" data-id = "{{ item.id }}" !! js文件中:添加属性 js逻辑使用 --- handleBing:(event)=>{ //event.target.dataset => data-自定义的数据获取 //编程式导航跳转 -API路由 //=》什么是tabbar页面 - 不能跳到tabbar页面 - tabbar绑定的页面 wx.navigatorTo({ url:'/...?id=' + event.target.dataset.id }) }
拿参=》页面跳转传参加载时,在新页面的onLoad 函数中拿到 query 参数
传参=》?查询字符串,navigation的 url属性 ? 拼接传参
data- 自定义的属性前缀 通过event.target.dataset
传参:
<navigator url="/pages/details/index?id={{item.id}}">
<text bindtap="handleDetail" data-id="{{item.id}}">{{item.title}}</text> // 点击跳转函数 handleDetail:(event)=>{ console.log('.....',event.target); wx.navigateTo({ url:'/pages/details/index?id=' + event.target.dataset.id }) }
获取参数:新页面的onLoad参数:
/** * 生命周期函数--监听页面加载 */ onLoad: function (query) { console.log('details:id',query); },
基础组件
编写 wxml 结构时,使用到的基本标签
view
scroll-view
swiper 、 swiper-item
image
text
navigator 类似 a
block 分组
API
wx.request()
wx.navigatorTo() 跳转非 tabbar 页面 【编程式 ?传参】
…
wxml
和 vue 模板语法类似
绑定数据 {{ expression }}
绑定事件
bindtap 【冒泡】catchtap 【阻止当前事件冒泡】、
bindtap
capture-bind 【传播】capture-catch 【阻止传播】
跳转到tabbar页面
<!-- 点击跳转到分类页面0tabbar页面 --> <text bindtap="handleCategory" wx:for="{{ categories }}" wx:key= "id" >{{item.name}}</text>
导航跳转到分类页面 - 即tabbar跳转 API switchTab 【不能带参数】
组件属性跳转 :
wx.switchTab({ url:'/pages/details/index' }) ------- <navigator open-type = 'switchTab'> <navigator> 存storage: // 导航跳转tabbar页面 handleCategory:(event)=>{ // 点击哪个分类传递对应分类id,查询数据 wx.setStorageSync('cid', event.target.dataset.id) wx.switchTab({ url: '/pages/category/index', }) } 取storage /** * 生命周期函数--监听页面显示onShow */ onShow: function () { let data = wx.getStorageSync('cid') console.log('cid',data); },
跳到分类页面的时候传 当前分类id 查询子分类
1-- 本地存储 实现传参 wx.setStorageSync-同步 Async-异步
同步结果直接返回 - 存储数据类型不限 【js中local存string】
2-- 全局globalData传递数据
组件内部共享数据
app.js
//自定义全局共享数据 globalData:{ cid:0, }
页面存取
//得到整个app对象 const app = getApp() //存取 app.globalData.cid = event.target.dataset.id //读取 const cid = app.globalData.cid
wx.reLaunch 重新启动
wx.redirectTo() 重定向
小程序登录
》wx.login获得临时登录凭证 - wx.request()发送code - 后端发给微信接口服务认证 - 返回信 息 - 自定义登录存入storage - request() 发送携带登录状态 -响应数据 getUserInfo()
》配合后端一起 -
<button bindtap="handleLogin">点击</button> ---------------- //登录 handleLogin(){ wx.getUserProfile({ desc: '描述用户信息', success(data){ console.log("success",data); }, fail(erro){ console.log(erro); } }) } --------------------- wx.getUserProfile({ //弹出授权框框 desc:'描述使用用户信息' success:res=>{}, //res.userInfo 拿到头像和昵称 fail:err=>{} })
picker选择器
camera相机 - 拍照功能 API - wx.createCamerCOntext
<!-- 相机 --> <view> <button bindtap="takephoto">拍照</button> <button bindtap="changePosition">切换摄像头</button> <camera style="height: 200px;width: 100%;" mode="normal" flash="on" device-position="{{ position }}" //改变摄像头朝向 ></camera> <text>拍照的图片为:</text> <image src="{{ tempImagePath }}"></image> </view>
//拍照 takephoto(){ //创建相机上下文对象 const cameraContext = wx.createCameraContext() //调用拍照方法 cameraContext.takePhoto({ success:(data)=>{ console.log('拍照成功',data); this.setData({ //保存拍照图片地址 tempImagePath:data.tempImagePath, }) }, fail:(error)=>{ console.log('拍照失败',error); } }) //扫码 扫码成功触发handleScancode - 打印event对象 event.detail.... <!-- 扫码 --> <camera style="height: 200px;width: 100%;" mode="scanCode" device-position="back" bindscancode="handleScancode" ></camera> //扫码成功后的回调 handleScancode(event){ console.log('扫码成功:',event.detail); },
-调用API 媒体 调出手机自身的相机
wx.chooseMedia() //可以录视频 wx.chooseImage() wx.chooseMedia() wx.scanCode({ ... }) --------------- handleCamera(){ let _this = this //API实现上传视频 wx.chooseMedia({ success(data){ console.log('上传视频:',data); _this.setData({ tempImagePath:data.tempFiles[0].tempFilePath }) } }) //API实现上传图片 wx.chooseImage({ count:2, success(data){ console.log('成功回调:',data); _this.setData({ tempImagePath:data.tempFilePaths }) }, fail(data){ console.log('失败回调',data); } }) },
map组件
<map // 地图中心是哪里 - 经纬度 langitude="经", latitude="纬" markers="标记点" show-location = "带有方向的定位点" //手机测试准确 enable-traffic = '{{true}}' // 实时路况 ></map> --------------------- 详情页-详情页-地图 <map longitude="104.066646" latitude="30.671305" show-location="{{true}}" enable-traffic="{{true}}" ></map> page,view{ w100%, h100%, }
更新客户端微信版本
wx.updateWeChatApp({ //监视客户版本过低,小程序不支持,会自动跳转到更新微信页面 })
showNavgationBarLoading()
showActionSheet()
wx.seetNavigationBarTitle() // 点击商品动态设置导航栏的标题
wx.uploadFile() downloadFile()
wx.stopwifi
wx.addPhoneContact()
wx.getNetworkType()
wx.makePhoneCall() //打电话
wx.uploadFile() wx.downloadFile()
组件自定义 【指南】
建立components目录/cart组件/js | wxml | wxss | json四类文件
json文件自定义组件声明
{ //json文件是个对象 "component":true,// 自定义组件声明 }
自定义组件结构 | 样式 书写
js 逻辑书写
//组件函数 =》自定义组件中的js是个组件函数 component({ properties:{ //只读 - 类型校验 item:{type:Object} }, data:{ //内部数据 }, methods:{ }, })
使用组件
//哪个页面使用,就在它的json文件标注: "usingComponents": { "xiaolan-upup":"/components/backTop/index" } ---------- { "usingComponent":{ "自定义组件名字":"/文件路径" } }
全局定义组件-
App.json文件中做 useingComponent: 注册,可以所有页面都使用
通信:===Vue通信
骨架屏
页面的空白版本,在页面完全渲染前,通过灰色模块来勾勒模块,等数据加载完毕后,在替换成真实的内容。
工具自带生成骨架屏 右下角点点点 - wx-if === wx:if
小程序进入的首页多了index.skeleton.wxml wxss两个文件
使用的时候在index.wxml wxss 引入代码
如果loading为true,显示骨架屏;//需要自己添加loading数据
数据读取完毕且更改之后之后,将loading改为false
loading:true, //骨架屏显示与否 ------------------------------------- setTimeout( async()=>{ try { let [cateData,homeData] =await Promise.allSettled([ request({ url:'/api/tabs'}), request({ url:'/api/tab/1'}) ]) // console.log('data:all',homeData,cateData); this.setData({ categories:cateData.value.list, banners:homeData.value.banners, productList:homeData.value.items.list, loading:false, //加载完数据后将骨架屏撤掉 }) } catch (error) { console.error(error) } },5000)
小程序也可以使用组件库—=》
Vant Weapp 小程序
步骤一:通过 npm 安装
》需要先 读npm 支持
文件资源管理器 : npm init -y =>创建package.json文件
根文件创建 miniprogram
npm install
npm i @vant/weapp -S --production
步骤二:按照流程修改配置
app.json 删除 style:v2
project.config.json添加配置
构建 npm 包
引入组件 app.json文件 :注意路径!!!
"van-button": "/miniprogram/miniprogram_npm/@vant/weapp/button/index"
页面通信
通过 url ?
本地存储
页面app全局定义数据 globalData
遇到的奇葩问题:
wxml代码避免换行,会识别源码格式
wx:for=" {{ categories }}" 引号多打了空格,显示失败
小程序框架
》多个平台都能运行小程序,除了写多套小程序外,也可以使用框架
mpvue 美团 vue2.x - 跨平台 18年没有维护
wepy
uni-app 基于mpvue…扩展 vuejs
taro 京东 react重度使用者 支持react-vue
uniApp
》快速上手 Vue语法写法 + 小程序标签
工具HbuilderX
建立项目-uni-app
模板 hello-uni-app 演示组件使用的 Vue版本选择
运行时开发环境的任务 npm start
发行 npm run build -原生App-(独立生成安装包…)构建完成后当前目录文件下生成unpackage文件
HBuilder:运行到小程序模拟器-需要各自的开发者工具安装-运行设置-小程序运行配置-开发工具路径需要配置一下–
微信开发者工具:设置-安全设置-安全-服务端口 开启命令行和HTTP才可以调用该工具
uniapp小程序案例- Dcloud插件市场
模板下载参照 - 小程序一个月完成
简历不要直接写 电商管理系统
写 == 江苏无锡旅游
uniapp小程序axios封装
ES6 Moudles 导入导出
做原生开发还是uniapp开发 套路 页面的配置 全局配置 那个文件中要清楚
uni-grid 网格
uni-app不能直接使用vue-router
插件市场有vueRrouter-ui等封装
配置文件是 pages.json 如何封装的axios?
登录
uni-forms uni-forms-item uni-esatinput
VUEx VUErOUTER
!条件编译
编译器 - 条件编译
平台差异-编写ifelse性能低-条件编译
特殊的注释
<!-- #ifdef APP-PLUS --> // #ifdef H5 ------------在注释中写这些!!--------- 原生APP 平台代码 #endif #ifdef H5 浏览器中才有 #endif #ifdef MP-WEIXIN 微信小程序中才有 #endif
微信的 wx.login方法获取用户信息,uni-app通过表单注册登录,如何根据不同平台进行差异编译
taro react语法+小程序标签
uniapp vue语法+小程序标签