用户在视图上的修改会自动同步到数据模型中去,一样若是数据模型中的数据发生改变,也会同步到视图层中。css
AppID
(在 微信开发者工具 新建小程序项目时须要)模拟器
编辑器
调试器
控制编辑器视图,iphone6
100%
WIFI
分别为机型选择、缩放比例、网络选择普通编辑
模式下,每次刷新都是从新载入index刷新,能够经过添加编译模式
,自定义刷新指定页面,这样方便调试预览
能够在手机上预览小程序远程调试
手机能够访问小程序,同时编辑器提供控制台一系列工具用于调试index.js
index.json
index.wxss
index.wxml
html
即app.json,app.json记录了一些全局配置:react
{ "pages": [ "pages/index/index", //第一项就是进入小程序的首页 "pages/calldetail/calldetail", "pages/finishcheck/finishcheck", ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#000", "navigationBarTitleText": "Hello", "navigationBarTextStyle": "white" }, "debug": true }
pages
页面路径window
页面的窗口表现tabBar
底部tab切换networkTimeout
网络超时时间debug
是否开启debug模式,debug模式下控制台会打印出详细调试信息
更多关于app.json,详细见官方文档css3
window
页面的窗口表现es6
enablePullDownRefresh
是否开启下拉刷新,当设置为true开启下拉刷新,backgroundColor
页面背景色在下拉的时候的“缝隙”中才会显示出来设置tabBar
时要和pages
一一对应:json
"pages": [ "pages/index/index", "pages/movie/movie", "pages/logs/logs" ], "tabBar": { "color": "#707070", "selectedColor": "#129763", "list": [ { "text": "首页", "pagePath": "pages/index/index", "iconPath": "common/img/main.png" }, { "text": "日志", "pagePath": "pages/logs/logs", "iconPath": "common/img/logs.png" }, { "text": "视频", "pagePath": "pages/movie/movie", "iconPath": "common/img/audio.png" } ] }
app.js中注册App,会获得一个程序实例,能够被其余页面访问小程序
App({ //程序实例 gldData: { a: 1 } })
页面js中注册Page:数组
Page({ //页面实例 //在页面中获取应用实例 //经过getApp全局函数获取应用实例 const app = getApp() pageData: { //自定义的页面数据 b: 2 } onLoad: function(){ //在本页面实例中访问pageData console.log(this.pageData) } })
onLaunch
onLaunch在小程序运行期间,只会运行一次;程序销毁(过了一段时间没有运行,或手动删除了小程序,再次添加运行)以后,再次启动就会执行onShow
每次在后台切换过来,就会执行onHide
每次切换到后台,就会执行缓存
onLoad
页面加载的时候执行,只会执行一次onReady
页面第一次渲染完成以后,只会执行一次onShow
页面显示的时候就会执行,能够执行屡次onHide
页面隐藏就会执行,能够执行屡次onUnload
页面卸载的时候执行,只会执行一次
进入小程序首页,会依次执行onLoad
onShow
onReady
,经过tabBar
从首页
切换到视频页
,index不会被卸载,因此不会执行onUnload,可是会执行onHide
,进入视频页,视频页会执行视频页的onLoad、onShow、onReady,而后再经过tabBar从视频页切换回首页,视频页执行onHide
,首页执行onShow
微信
在首页中加入导航navigator,经过navigator的方式跳转到视频页,首页仍是会执行隐藏方法onHide
,视频页左上角出现返回的返回方式,用这种返回方式返回到首页,视频页会发生销毁执行onUnload
let arr1 = [ 'Matt', 'Moly', 'Joe', 'Hurley' ] let arr2 = [ {id: Math.random(), name: 'Matt'}, {id: Math.random(), name: 'Moly'}, {id: Math.random(), name: 'Joe'}, {id: Math.random(), name: 'Hurley'} ] Page({ data: { arrNames: arr1 arr2Names: arr2 } }) <view wx:for="{{arrNames}}" wx:key="*this">{{item}}</view> <view wx:for="{{arr2Names}}" wx:key="id">{{item.name}}</view>
均可以循环渲染出name
Page({ data: { score: 80 } }) <view wx:if="{{score>70 && score<90}}">等级B</view> <view wx:elif="{{score<70 && score>30}}">等级C</view> <view wx:elif="{{score<30}}">等级D</view> <view wx:else>等级A</view>
block
并非真正的元素,用来辅助渲染一些平级的元素
<block wx:if="{{score===80}}"> <view>{{name}}</view> <view>{{score}}</view> <view>等级A</view> </block> <block wx:else>学生不符合要求</block>
//定义好template,指定name <template name="hello"> <view>这是hello行</view> </template> //在页面中须要用到template的地方使用template,is和name要对应起来,这样页面上就能渲染出template中的内容 <template is="hello"></template>
//gender为动态内容 <template name="hello"> <view>{{gender}}</view> </template> //相似react,这里传入变量gender,对象的形式 <template is="hello" data="{{gender: 'female'}}"></template>
<template name="renderList"> //渲染这个模板时就须要names这样一个数组 <text>分数:{{score}}</text> <block wx:for="{{names}}" wx:key="id"> <view>{{item.name}}</view> <view>哈哈哈</view> </block> </template> <template is="renderList" data="{{names, score}}"></template> //js的data中已经定义了names和score
template.wxml
),放置的位置视状况而定;<import src="template.wxml"/>
(这里template.wxml和页面wxml在同一目录下)header.wxml
),在页面中的引入方式:<include src="header.wxml"/>
<view bind:tap="onTap"> <text>点按我能够打印信息</text> </view> onTap(){ console.log("我是谁") }
其中,bind:tap
中的冒号能够不写bindtap
事件函数中额外自带事件对象参数:
onTap(e){ console.log(e) }
<view bind:tap="onTap" id='view' data-name="容器"> <text id="text" data-name="文字">点按我能够打印信息</text> </view> onTap(e){ console.log(e) }
点击view空白部分:
点击text文字:
bindtap
不阻止事件冒泡catchtap
阻止事件冒泡
<view catch:tap="onTap" id='view' data-name="容器"> <text id="text" data-name="文字">点按我能够打印信息</text> </view>
rpx规定屏幕宽为750px
.class
#id
element
element, element
:after
:before
(好比不支持css3的属性选择器)
<text style='color: {{color}}'>点按我能够打印信息</text> data: { color: 'red' }
<!--index.wxml--> <view class="container"> <wxs module="tool"> function createName(names) { return names.split(',') } module.exports = createName </wxs> <!-- tool就是wxs导出的函数 --> <!-- names为js中data定义的 --> <view wx:for="{{tool(names)}}">{{item}}</view> </view> <!--index.js--> data: { names: "Alice,John,Sara,Dave" }
wxs也能够独立出来:
<!--tool.wxs--> function createName(names) { return names.split(',') } module.exports = createName <!--index.wxml--> <view class="container"> <!--tool.wxs和index.wxml在同一目录下--> <wxs src="tool.wxs" module="tool"></wxs> <view wx:for="{{tool(names)}}">{{item}}</view> </view>
wxs不支持es6
<view>{{magicNumber}}</view> <button bindtap='onTap'>点击</button> data: { magicNumber: Math.random() }, onTap(){ //this.data.magicNumber = 8999 //这种更新方式是没用的 this.setData({ magicNumber: Math.random() //相似react更新方式 }) }
data变化,视图不必定更新,这是一个异步的过程。
<input type="text" value="hello" bindinput='onInputChange'></input> onInputChange(e){ console.log(e) //return Math.random() //还能够return出去一个值,控制输入框东西的显示 }
在输入框输入的时候,控制台不断打印事件对象,e.detail.value即为输入框内容
自定义组件,能够单独出来:
Component
注册组件Component
注册的是组件,Page
注册的是页面
而后在页面的json文件中注册自定义组件:
在页面中使用自定义组件:
<!--index.wxml--> <magic-number></magic-number>
其中,在magicNumber.wxml中
<text>magicNumber自定义组件</text>
因此在index页面中显示的就是文字“magicNumber自定义组件”。
<!-- mnum.wxml --> <text bindtap="onTap">{{magicNumber}}</text> // mnum.js Component({ data: { magicNumber: Math.random() }, methods: { //组件里事件的回调函数要统一写在methods里 onTap(e) { this.setData({ magicNumber: Math.random() }) } } })
<!-- mnum.wxml --> <text bindtap="onTap">{{magicNumber}}</text> // mnum.js Component({ data: { magicNumber: Math.random() }, methods: { //组件里事件的回调函数要统一写在methods里 onTap(e) { this.setData({ magicNumber: Math.random() }) // 在自定义组件的事件回调函数中,还能够另外再触发事件,名称自定义,用于页面中使用 // 另外能够携带一些参数到页面(这里data中的magicNumber) this.triggerEvent('getMagicNumber', this.data.magicNumber) } } }) // mnum.json { "component": true } <!--index.wxml--> <magic-number bind:getMagicNumber="onGetMagicNumber"></magic-number> // index.js onGetMagicNumber(e){ console.log(e) }
点击index中显示的自定义组件文字,控制台打印处相关信息:
点击文字页面取整显示:
<!-- mnum.wxml --> <text bindtap="onTap">{{magicNumber}}</text> <!--mnum.js--> Component({ data: { magicNumber: Math.random() }, methods: { //组件里事件的回调函数要统一写在methods里 onTap(e) { this.setData({ magicNumber: Math.random() }) // 在自定义组件的事件回调函数中,还能够另外再触发事件,名称自定义,用于页面中使用 // 另外能够携带一些参数到页面(这里data中的magicNumber) this.triggerEvent('getMagicNumber', this.data.magicNumber) } } }) <!--mnum.json--> { "component": true } <!--index.wxml--> <magic-number bind:getMagicNumber="onGetMagicNumber"></magic-number> <view>{{num}}</view> // index.js Page({ data: { num: null }, onGetMagicNumber(e){ this.setData({ //e.detail即为那个值 num: Math.floor(e.detail*1000) }) } })
点击文字,index页面中的{{num}}也跟着变化,可是在页面初始状态,{{num}}显示的是null,为了让{{num}}与自定义组件中的随机数一致,在自定义组件的生命周期函数中:
自定义组件的自定义属性要小写,并用烤串形式:
<!-- mnum.wxml --> <text>{{nowIn}} is here!</text> // mnum.js Component({ properties: { // js为驼峰式,页面中为烤串式 nowIn: String }, attached(){ //组件中经过this.data获取到properties进而获取到nowIn console.log(this.data) } }) <!--mnum.json--> { "component": true } <!--index.wxml--> <magic-number now-in="Index" bind:getMagicNumber="onGetMagicNumber"> </magic-number>
页面显示为Index is here!
,控制台打印信息为{nowIn: "Index"}
小程序里两种方式实现导航:navigator
使用API进行导航
具体参数可在官网查阅 关于navigator
open-type
的属性值——navigate
跳转到switchTab
以tab方式切换页面navigateBack
页面回退redirect
重定向reLaunch
从新加载url页面,顶部不会出现回退按钮
<navigator url='/pages/movie/movie' open-type='navigate' >到movie</navigator> <!-- open-type的默认值为navigate --> <navigator url='/pages/about/about'>到about</navigator>
navigate(跳转到)
navigator方式,顶部会出现回退的样式:
<navigator url='/pages/movie/movie' open-type='switchTab'>以tab方式切换到movie页</navigator>
<!-- 要实现以tab方式切换页面,在app.json中要配合写上tab的配置项 -->
<navigator open-type='navigateBack'>回退</navigator>
<!--index.wxml--> <view>首页</view> <navigator url='/pages/about/about'>到about</navigator> <!--pages/about/about.wxml--> <view>about页</view> <navigator url='/pages/movie/movie' open-type='redirect'>重定向到movie页</navigator> <!--pages/movie/movie.wxml--> <view>movie页</view> <navigator url="/pages/about/about">去about</navigator>
从首页进入about页,在about页重定向到movie页,点击顶部的回退,直接回退到首页,而不是about页 index-about-在about页重定向到movie页-到movie页后点击顶部回退-直接回到index页
<!--index.wxml--> <view>首页</view> <navigator url='/pages/about/about'>到about</navigator> <!--pages/about/about.wxml--> <view>about页</view> <navigator url='/pages/movie/movie' open-type='reLaunch'>reLaunch movie页</navigator> <!--pages/movie/movie.wxml--> <view>movie页</view> <navigator url="/pages/about/about">去about</navigator>
在首页进入about页,在about页以reLaunch的方式进入movie页,movie页就是小程序当前加载的惟一页面 index-about-在about页以reLaunch方式进入movie页-movie页,当前小程序加载的惟一页面,顶部没有返回按钮
navigate
wx.navigateTo(OBJECT)
跳转到redirect
wx.redirectTo(OBJECT)
重定向switchTab
wx.switchTab(OBJECT)
跳转到某个tabnavigateBack
wx.navigateBack(OBJECT)
回退reLaunch
wx.reLaunch(OBJECT)
重加载
<!--index.wxml--> <view>首页</view> <view bindtap='onGotoMovie'>使用API方式跳转到movie</view> // index.js Page({ onGotoMovie(){ wx.navigateTo({ url: '/pages/movie/movie', }) } })
点击便可以navigate的方式跳转到movie页
受权方式:用户信息
(受权button)其余信息受权
(wx.authorize(OBJECT)先进行受权直接获取信息,未受权会先进行受权)
<!--index.wxml--> <!-- 点击出现用户受权弹框,点击取消或者肯定会执行回调函数 --> <!-- onGetUserInfo即为执行的回调 --> <button open-type='getUserInfo' bindgetuserinfo='onGetUserInfo'>获取用户信息</button> // index.js Page({ onGetUserInfo(e){ //接收一个事件对象,将其打印出来 console.log(e) } })
点击按钮,用户出现受权弹窗:(以前进行过受权操做可先清除受权数据)
e.detail.userInfo为用户的一些基本信息
<!--index.wxml--> <button bindtap='onAuthLocation'>受权位置</button> // index.js Page({ onAuthLocation(){ wx.authorize({ //只是进行受权 scope: 'scope.userLocation', success: msg=>console.log(msg, 'location success'), fail: e=>console.log(e, 'location fail') }) } })
点击按钮,出现受权弹窗,根据用户的选择,会执行success或者fail的回调:
以点击容许为例,控制台打印为:
<!--index.wxml--> <button bindtap='onGetLocation'>获取位置</button> // index.js Page({ onGetLocation(){ wx.getLocation({ //获取到受权后的信息 success: msg=>console.log(msg, "位置"), fail: e=>console.log(e, "没获取到位置") }) } })
点击按钮:
选择肯定,控制台就会打印出地理信息相关信息:
<!--index.wxml--> <button bindtap='onGetSetting'>获取受权信息</button> // index.js Page({ onGetSetting(){ wx.getSetting({ //微信提供这样一个API用于告诉哪些信息受权了哪些信息没有受权 success: msg => console.log(msg, "受权相关信息"), }) } })
<!--index.wxml--> <button bindtap='onGotoSetting'>打开受权信息面板</button> // index.js Page({ onGotoSetting(){ wx.openSetting({ success: msg=>console.log(msg, "设置完成") }) } })
点击能够进入受权面板:
微信里能够同步或者异步地缓存数据
<!--index.wxml--> <button bindtap='onCache'>缓存数据</button> // index.js Page({ onCache(){ wx.setStorage({ key: 'name', data: {p1: 'Matt'}, //data能够指定字符串,也能够指定对象 success: ()=>{ wx.getStorage({ key: 'name', success: data=>{ console.log(data) } }) } }) } })
点击按钮,便可实现缓存:
同时能够取到缓存中name为key的缓存数据,在控制台打印出来:
以上设置缓存的方式是异步的。
如下为同步设置缓存的方式:
<!--index.wxml--> <button bindtap='onCache'>缓存数据</button> // index.js Page({ onCache(){ wx.setStorageSync('names', 'Hurley') let ns = wx.getStorageInfoSync('names') console.log(ns) } })
点击按钮,缓存中写入names:
并在控制台打印出:
<!--index.wxml--> <view>{{name}}</view> <button bindtap='onSet'>设置缓存数据</button> <button bindtap='onGetName'>获取name</button> <button bindtap='onRemoveName'>移除name</button> // index.js Page({ data: { name: 'hello' }, onSet(){ wx.setStorageSync('name', 'Hurley') }, onGetName(){ let n = wx.getStorageSync("name") console.log(n) if(n){ this.setData({ name: n }) } }, onRemoveName(){ //缓存中key为“name”的缓存被移除 wx.removeStorageSync('name') } })
点击“设置缓存数据”,缓存中写入key为“name”的缓存;
而后点击“获取name”,从缓存中获取到key为“name”的value值,并更新到data中的name,在视图中{{name}}也会更新;
而后点击“移除name”,缓存中key为“name”的缓存数据被移除。
<!--index.wxml--> <button bindtap='onReq'>请求服务</button> // index.js Page({ onReq(){ wx.request({ url: 'http://localhost:3000/hello', data: { name: 'Joe' }, method: 'POST', success: data=>{ console.log(data) } }) } })
点击按钮,控制台出现报错:
所以,在小程序里进行请求须要进行相应配置:
这样就能够经过接口请求到数据,快速调试时设置不校验域名,能够请求到数据