走進小程序
- 微信?程序的注冊流程
- 去微信公眾平臺注冊?程序賬號
- 獲得appid和appsecret
- 微信開發(fā)者?具安裝及使?講解
-
出現(xiàn)合法域名校驗錯誤
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(當小程序初始化完成時肚逸,會觸發(fā) onLaunch(全局只觸發(fā)一次))
- onshow(顯示或者切換到前臺)
- onhide(切換到后臺)
?程序啟動時先執(zhí)行小程序整體生命周期的onlauch>onshow,然后在執(zhí)行??的生命周期onload>onshow>onready
- ???命周期
- onload
- onshow
- onready
- onhide
- onunload
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載(只第一次)
*/
onLoad: function(options) {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面初次渲染完成(只第一次)
*/
onReady: function() {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面顯示
*/
onShow: function() {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面隱藏
*/
onHide: function() {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面卸載(代碼關閉頁面)
*/
onUnload: function() {
},
/**
* 頁面相關事件處理函數(shù)--監(jiān)聽用戶下拉動作
*/
onPullDownRefresh: function() {
},
/**
* 頁面上拉觸底事件的處理函數(shù)
*/
onReachBottom: function() {
},
/**
* 用戶點擊右上角分享
*/
onShareAppMessage: function() {
}
-
?程序?適應尺?單位rpx
rpx單位:是可以根據(jù)屏幕寬度進??適應
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
數(shù)據(jù)綁定與事件交互
- 數(shù)據(jù)綁定的概念
- Mustache 語法(雙?括號)
{{textstr+2}}
- 單向數(shù)據(jù)綁定 - 動態(tài)數(shù)據(jù)綁定
- ?程序data賦值
this.setData(對象)
- 獲取data?的值
> this.data.(key值) - 條件渲染
- wx:if為true就顯示元素硕淑,false不顯示
- 語法
<view wx:if="{{score<60}}">不及格</view> <view wx:elif="{{score>=80}}">優(yōu)秀</view> <view wx:else>良好</view>
- 列表渲染
- wx:for綁定數(shù)組课竣,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
一般直接把循環(huán)放到view上即可置媳,如果需要兩個view(甚至多個view)沒有父級view于樟,則可以通過block包裹;block最終不會在在界面顯示拇囊,只是一個邏輯載體
-
綁定事件與事件交互
- bind+事件
<button bindtouchstart="changeData" bindtouchend="tmove"bindlongpress="lpress">改變數(shù)據(jù)</button>
- 需要在js?寫對應的?法
//點擊事件 changeData:function(){ this.setData({ textStr:"hello ?程序" }) }, //觸摸移動 tmove:function(){ console.log("touchend"); }, //?按觸發(fā) 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(綁定事件)
事件捕獲是從上到下捕獲,然后才會向上冒泡寥袭,所以都是捕獲事件從上到下執(zhí)行路捧,然后冒泡事件從下到上。
阻止冒泡:例如點擊?程序三個字传黄,則如果使用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}}">
優(yōu)秀
</view>
<view wx:elif="{{num>60}}">
及格
</view>
<view wx:else>
不及格
</view>
<!-- 通過這種方式傳遞數(shù)據(jù)到事件里面data-* -->
<button data-num="90" bindtap="tapFlag">優(yōu)秀</button>
<button data-num="65" bindtap="tapFlag">及格</button>
<button data-num="20" bindtap="tapFlag">不及格</button>
// pages/index/index.js
Page({
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
arrTitles: [],
num:90
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載
*/
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字符串窗声,但是不能綁定數(shù)據(jù){{}})
<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(手動實現(xiàn)雙向數(shù)據(jù)綁定)
- label
- radio
- textarea
// pages/index/index.js
Page({
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
str:'傳遞',
textStr:"<div>哈哈{{str}}</div>"
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載
*/
onLoad: function(options) {
},
inputFN:function(e){
//實現(xiàn)雙向數(shù)據(jù)綁定
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實現(xiàn)輪播圖
<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
- 可滾動視圖區(qū)域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實現(xiàn)可滾動導航欄
<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(){
//回調(diào)成功函數(shù)
console.log(111)
}
})
導航組件文檔: https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html
- 路由跳轉?法
- wx.navigateTo()保留當前??辜纲,跳轉到應?內(nèi)的某個??笨觅。但是不能跳到 tabbar (底部切換欄)??
- wx.switchTap()跳轉到 tabBar ??拦耐,并關閉其他所有? tabBar ??
- wx.reLaunch()關閉所有??,打開到應?內(nèi)的某個??
- wx.redirectTo()關閉當前??见剩,跳轉到應?內(nèi)的某個??杀糯。但是不允許跳轉到 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>
//下個頁面獲取參數(shù)
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": "個?"
}]
},
- 方式二:代碼設置
//動態(tài)設置 tabBar 某一項的內(nèi)容苍苞,2.7.0 起圖片支持臨時文件和網(wǎng)絡文件
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案例
- 價格保留?數(shù)
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;
}