走进小程序
- 微信⼩程序的注册流程
- 去微信公众平台注册⼩程序账号
- 获得appid和appsecret
- 微信开发者⼯具安装及使⽤讲解
-
出现合法域名校验错误
1.png
-
解决:详情⾥勾上“不校验安全域名、web-view 域名、TLS 版本以及 HTTPS 证书”
- ⼩程序⽬录结构分析
⼩程序的主体部分:
- app.js (⼩程序主要逻辑层,⽤来注册⼩程序)
- app.json(⼩程序公共配置)
- app.wxss(⼩程序公共样式)
app.json(全局的配置)
{
"pages": [
"pages/index/index"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "哈哈",
"navigationBarTextStyle": "black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
index.json(单个页面的配置文件,会覆盖全局的)
{
"usingComponents": {},
"navigationBarBackgroundColor": "#000000",
"navigationBarTextStyle": "white"
}
同理:index.wxss也会覆盖app.wxss
第一个小程序
- 新建⼀个⼩程序及框架组成介绍
- 新建⻚⾯的步骤
- 右键新建page⽣成⻚⾯的框架
- 在app.json中的pages添加我们新建⻚⾯的路径
- 新建⻚⾯的步骤
- ⼩程序⽣命周期和⻚⾯⽣命周期讲解
- ⼩程序⽣命周期:
- onlauch(当小程序初始化完成时,会触发 onLaunch(全局只触发一次))
- onshow(显示或者切换到前台)
- onhide(切换到后台)
⼩程序启动时先执行小程序整体生命周期的onlauch>onshow,然后在执行⻚⾯的生命周期onload>onshow>onready
- ⻚⾯⽣命周期
- onload
- onshow
- onready
- onhide
- onunload
/**
* 生命周期函数--监听页面加载(只第一次)
*/
onLoad: function(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成(只第一次)
*/
onReady: function() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function() {
},
/**
* 生命周期函数--监听页面卸载(代码关闭页面)
*/
onUnload: function() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function() {
}
-
⼩程序⾃适应尺⼨单位rpx
rpx单位:是可以根据屏幕宽度进⾏⾃适应
2.png
一般使用iphone6设计稿 因为好换算 1px=2rpx
- flex弹性布局
- 在⽗容器上加上display:flex,将我们⽗容器编程弹性容器
.sort_box { display: flex; flex-direction: row;//⽔平排列 margin: 0 30rpx; justify-content: space-around;//每个项⽬的两端间隔相等 }
flex布局博客:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
数据绑定与事件交互
- 数据绑定的概念
- Mustache 语法(双⼤括号)
{{textstr+2}}
- 单向数据绑定 - 动态数据绑定
- ⼩程序data赋值
this.setData(对象)
- 获取data⾥的值
> this.data.(key值) - 条件渲染
- wx:if为true就显示元素,false不显示
- 语法
<view wx:if="{{score<60}}">不及格</view> <view wx:elif="{{score>=80}}">优秀</view> <view wx:else>良好</view>
- 列表渲染
- wx:for绑定数组,wx:for-item值为当前项⽬的变量名,wx:for-index值为当前下标的变量名
<block wx:for="{{list}}" wx:for-item="course" wx:for-index="idx"> <view class="item"> <view class="item_img"> <image src="{{course.img}}"></image> </view> <view class="item_name">{{course.name}}</view> <view>{{idx}}</view> </view> </block>
列表渲染文档: https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/list.html#wx:key
一般直接把循环放到view上即可,如果需要两个view(甚至多个view)没有父级view,则可以通过block包裹;block最终不会在在界面显示,只是一个逻辑载体
-
绑定事件与事件交互
- bind+事件
<button bindtouchstart="changeData" bindtouchend="tmove"bindlongpress="lpress">改变数据</button>
- 需要在js⾥写对应的⽅法
//点击事件 changeData:function(){ this.setData({ textStr:"hello ⼩程序" }) }, //触摸移动 tmove:function(){ console.log("touchend"); }, //⻓按触发 lpress:function(){ console.log("longpress") },
-
事件机制--catch与bind
- bind会应⽤到冒泡机制,catch会阻⽌事件冒泡
<view class="box" bindtap="containerTap"> <text catchtap="txtTap">⼩程序</text> </view>
- 捕获阶段的bind与catch,绑定事件需要加上冒号
capture-bind:tap(绑定事件) capture-catch:tap(绑定事件)
事件捕获是从上到下捕获,然后才会向上冒泡,所以都是捕获事件从上到下执行,然后冒泡事件从下到上。
阻止冒泡:例如点击⼩程序三个字,则如果使用catchtap绑定txtTap则事件不会向上冒泡,也就是说bindtap="containerTap"
不会响应,但是如果bindtap="txtTap"则会冒泡的。
事件捕获:也分为bind和catch;如果是capture-bind:tap的事件会向下传递,下级也会捕获;
如果capture-catch:tap则不会把事件向下传递,下级不会捕获;所以catch也会在这里阻塞下级捕获;
- 案例
<!--pages/index/index.wxml-->
<view class="sort">
<block wx:for="{{arrTitles}}" wx:for-item="item">
<view class="item">
<view class="radio">{{item.icon}}</view>
<text>{{item.title}}</text>
</view>
</block>
</view >
<view wx:if="{{num>70}}">
优秀
</view>
<view wx:elif="{{num>60}}">
及格
</view>
<view wx:else>
不及格
</view>
<!-- 通过这种方式传递数据到事件里面data-* -->
<button data-num="90" bindtap="tapFlag">优秀</button>
<button data-num="65" bindtap="tapFlag">及格</button>
<button data-num="20" bindtap="tapFlag">不及格</button>
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
arrTitles: [],
num:90
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
let a = [{
icon: "前",
title: "前端"
}, {
icon: "后",
title: "后端"
}, {
icon: "运",
title: "运维"
}, {
icon: "测",
title: "测试"
}];
this.setData({
arrTitles: a
})
},
tapFlag: function (event){
//通过event.target.dataset.num获取传参
this.setData({
num: event.target.dataset.num
})
}
})
/* pages/index/index.wxss */
.sort {
display: flex;
flex-direction: row;
justify-content: space-around;
}
.sort .item .radio {
border-radius: 50%;
color: white;
height: 80rpx;
width: 80rpx;
line-height: 80rpx;
background-color: blue;
margin-bottom: 30rpx;
}
.sort .item {
text-align: center;
}
⼩程序基础组件
- 基础组件
- icon
<icon type="warn" size="100rpx" color="red"></icon>
- progress
<progress percent="30" show-info="true" border-radius="10" strokewidth="50rpx" activeColor="red" backgroundColor="#000" active="true">
</progress>
- rich-text(可以插入html字符串,但是不能绑定数据{{}})
<rich-text nodes="{{textStr}}"></rich-text>
- text
<text selectable="true">⼩程序</text>
官⽅⽂档:https://developers.weixin.qq.com/miniprogram/dev/component/text.html
- ⼩程序常⽤表单组件
- 常用表单组件
- button
- checkbox
- form
- input(手动实现双向数据绑定)
- label
- radio
- textarea
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
str:'传递',
textStr:"<div>哈哈{{str}}</div>"
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
},
inputFN:function(e){
//实现双向数据绑定
this.setData({
str:e.detail.value
})
}
})
<!--pages/index/index.wxml-->
<input bindinput="inputFN">请输入</input>
<text>{{str}}</text>
<rich-text nodes="{{textStr}}"></rich-text>
表单组件: https://developers.weixin.qq.com/miniprogram/dev/component/button.html
- 其他组件
- picker组件
<picker bindchange="bindPickerChange" value="{{index}}" range=" {{array}}"> <view class="picker"> 当前选择:{{array[index]}} </view> </picker>
- slider组件
<slider min="50" max="200" show-value="true" step="5"></slider>
- switch组件
<switch bindchange="bindSwitchChange" checked="true"></switch>
- ⼩程序媒体组件
- audio组件
<audio id="myAudio" poster="{{poster}}" name="{{name}}" author=" {{author}}" src="{{src}}" controls></audio> <button bindtap="audipplay">播放</button> <button bindtap="audippause">暂停</button> <button bindtap="audioseek">设置进度条</button>
- video组件
<video src="https://www.w3school.com.cn/i/movie.ogg" controls></video>
- image组件
<image lazy-load="true" src="../../images/sp2.png"></image>
- ⼩程序地图组件map
map⽂档: https://developers.weixin.qq.com/miniprogram/dev/component/ - ⼩程序画布组件canvas
canvas⽂档: https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html
<canvas style="width:600rpx;height:400rpx;" canvas-id="canvas"></canvas>
onReady: function() {
console.log("ready");
var context = wx.createCanvasContext('canvas');
context.setStrokeStyle("#ff0000");
context.setLineWidth(2);
context.moveTo(160,100);
context.arc(100,100,60,0,2*Math.PI,true);
context.moveTo(140,100);
context.arc(100,100,40,0,Math.PI,false);
context.moveTo(85,80);
context.arc(80,80,5,0,2*Math.PI,true);
context.moveTo(125,80);
context.arc(120, 80, 5, 0, 2 * Math.PI, true);
context.stroke();
context.draw();
}
常⽤视图容器及路由跳转
- 视图容器swiper实现轮播图
<swiper class="swiper" autoplay="true" interval="3000" duration="1000"
indicator-dots="true" indicator-active-color="#007aff" vertical="true"
circular="true" display-multiple-items="2">
<block wx:for="{{imgs}}">
<swiper-item>
<image src="{{item}}" class="item_img"></image>
</swiper-item>
</block>
</swiper>
swiper⽂档: https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html
- 可滚动视图区域scroll-view
- 横向滚动
<scroll-view scroll-x="true" style="display:flex;white-space:nowrap;">
<block wx:for="{{imgs}}">
<image src="{{item}}"></image>
</block>
</scroll-view>
- 纵向滚动
<scroll-view scroll-y="true" scroll-top="100" style="height:340rpx;"
scroll-into-view="{{toView}}" bindscrolltoupper="upper"
bindscrolltolower="lower">
<block wx:for="{{imgs}}">
<image src="{{item}}" id="{{'img'+index}}"></image>
</block>
</scroll-view>
<button bindtap="gotoview">定位到第三张</button>
- scroll-view实现可滚动导航栏
<scroll-view scroll-x="true" class="nav" scroll-left="{{navScrollLeft}}">
<block wx:for="{{navData}}" wx:key="index">
<view class="nav_item {{currentNav == index?'active':''}}" data-current="
{{index}}" bindtap="switchNav">{{item.text}}</view>
</block>
</scroll-view>
点击移动scroll-view,添加active类
switchNav:function(e){
// console.log(e);
var cur = e.currentTarget.dataset.current;
//tab选项居中
var singleWidth = this.data.windowWidth/5;
this.setData({
navScrollLeft: (cur - 2)*singleWidth
});
console.log(this.data.navScrollLeft);
if(this.data.currentNav == cur) {
return false;
}else{
this.setData({
currentNav: cur
})
}
},
- 特殊覆盖组件cover-view及cover-image
<video src="https://www.w3school.com.cn/i/movie.ogg" controls>
<cover-view class="shuiyin">
⼩D课堂
<cover-image src="../../images/sp2.png"></cover-image>
</cover-view>
</video>
cover-view文字遮盖层cover-image图片遮盖层
- ⻚⾯导航组件
<!-- 方式一 -->
<navigator url="/pages/personal/personal">跳转到个⼈⻚⾯</navigator>
//方式二
wx.navigateTo({
url: '/pages/user/user?name=zq',
success:function(){
//回调成功函数
console.log(111)
}
})
导航组件文档: https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html
- 路由跳转⽅法
- wx.navigateTo()保留当前⻚⾯,跳转到应⽤内的某个⻚⾯。但是不能跳到 tabbar (底部切换栏)⻚⾯
- wx.switchTap()跳转到 tabBar ⻚⾯,并关闭其他所有⾮ tabBar ⻚⾯
- wx.reLaunch()关闭所有⻚⾯,打开到应⽤内的某个⻚⾯
- wx.redirectTo()关闭当前⻚⾯,跳转到应⽤内的某个⻚⾯。但是不允许跳转到 tabbar ⻚⾯
- wx.navigateBack()关闭当前⻚⾯,返回上⼀⻚⾯或多级⻚⾯
- 路由跳转⽂档:https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateBack.html
- ⻚⾯的传参与取参
<navigator url="/pages/sort/sort?id=1&name=eric">跳转到分类</navigator>
//下个页面获取参数
onLoad: function (options) {
console.log(options.name)
console.log(options.id)
}
- ⼩程序的底部导航栏
- 方式一:通过配置方式
app.json
"tabBar": {
"color": "#2b333b",
"selectedColor": "#3bb149",
"borderStyle": "black",
"list": [{
"pagePath": "pages/index/index",
"text": "⾸⻚"
},{
"pagePath": "pages/sort/sort",
"text": "分类"
},{
"pagePath": "pages/personal/personal",
"text": "个⼈"
}]
},
- 方式二:代码设置
//动态设置 tabBar 某一项的内容,2.7.0 起图片支持临时文件和网络文件
wx.setTabBarItem({
index: 0,
text: 'text',
iconPath: '/path/to/iconPath',
selectedIconPath: '/path/to/selectedIconPath'
})
tabbar文档:https://developers.weixin.qq.com/miniprogram/dev/extended/weui/tabbar.html
setTabBarItem文档:https://developers.weixin.qq.com/miniprogram/dev/api/ui/tab-bar/wx.setTabBarItem.html
构建模板化与模块化⼩程序
- 利⽤require⽅法加载js模块⽂件
- require路径要写成相对路径
var util = require('../../utils/util.js');
- WXML模板编写与引⼊
- 新建模板⽂件,wxml和wxss
<template name="courseList">
<view class="item">
<view class="item_img">
<image src="{{course.img}}"></image>
</view>
<view class="item_name">{{course.name}}</view>
<view>{{idx}}</view>
</view>
</template>
- 在需要⽤的⻚⾯import模板⽂件
<view class="list">
<block wx:for="{{list}}" wx:for-item="course" wx:for-index="idx">
<template is="courseList" data="{{course}}"></template>
</block>
</view>
- wxs模块引⽤
- 使用
<wxs src="../../wxs/common.wxs" module="info"></wxs>
<view>{{info.message}}</view>
<view>{{info.add(20,10)}}</view>
- wxs⽂件
//JS代码
var msg = "hello world";
//commonjs模块化导出
var num = function (num1, num2) {
return num1 + num2;
}
module.exports = {
message: msg,
add: num
}
- wxs案例
- 价格保留⼩数
var toFixed = function(value,count){
return value.toFixed(count);
}
- 时间戳格式化
var formatNumber = function (n) {
n = n.toString()
return n[1] ? n : '0' + n
}
var regYear = getRegExp("(y+)", "i");
var dateFormat = function (timestamp, format) {
if (!format) {
format = "yyyy-MM-dd hh:mm:ss";
}
timestamp = parseInt(timestamp);
var realDate = getDate(timestamp);
function timeFormat(num) {
return num < 10 ? '0' + num : num;
}
var date = [
["M+", timeFormat(realDate.getMonth() + 1)],
["d+", timeFormat(realDate.getDate())],
["h+", timeFormat(realDate.getHours())],
["m+", timeFormat(realDate.getMinutes())],
["s+", timeFormat(realDate.getSeconds())],
["q+", Math.floor((realDate.getMonth() + 3) / 3)],
["S+", realDate.getMilliseconds()],
];
var reg1 = regYear.exec(format);
// console.log(reg1[0]);
if (reg1) {
format = format.replace(reg1[1], (realDate.getFullYear() +
'').substring(4 - reg1[1].length));
}
for (var i = 0; i < date.length; i++) {
var k = date[i][0];
var v = date[i][1];
var reg2 = getRegExp("(" + k + ")").exec(format);
if (reg2) {
format = format.replace(reg2[1], reg2[1].length == 1
? v : ("00" + v).substring(("" + v).length));
}
}
return format;
}
网友评论