微信小程序教程

微信小程序

一. 小程序环境

http://www.php.cn/js/js-MINA.html

https://developers.weixin.qq.com/miniprogram/dev/index.html?t=2018413

1.介绍

微信小程序,简称小程序,缩写XCX,英文名Mini Program,是一种不需要下载安装即可使用的应用,用户扫一扫即可打开应用

开放申请的主体类型为企业,政府,媒体,其他组织或个人的开发这,均可申请注册小程序。小程序、订阅号、服务号、企业号、是并行的体系

2016111日,腾讯内部研究新的服务好形态,叫 微信小程序

2016921日,微信小程序正式开启内测

201719日,张小龙在2017微信公开课Pro上发布的小程序正式上线

2.注册下载

https://developers.weixin.qq.com/miniprogram/introduction/

1.注册流程

2.注册网址:https://mp.weixin.qq.com/

3.微信扫码登陆

3.开通腾讯云:点击开发者工具,点击腾讯云,点击开通,

4.扫码进入开发

5.下载微信开发者工具

6.购买域名及服务器:点击生产环境,购买域名以及服务器

7.安装微信开发者工具,登录

    

3. 查找API

https://developers.weixin.qq.com/miniprogram/dev/index.html?t=2018413

1.

2.

4. 新建项目

5. 小程序配置

1.全局配置app.json

微信小程序的全局配置保存在app.json文件中,开发者通过app.json来配置页面文件(pages)的路径、窗口(window)表现、设定网络时间 (networkTimeout)以及配置多个切换页(tarBar)等

2.工具配置: project.config.json

小程序开发者工具在每个项目的根目录都会生成一个 project.config.json,你在工具上做的任何配置都会写入到这个文件,当你重新安装工具或者换电脑工作时,你只要载入同一个项目的代码包,开发者工具就自动会帮你恢复到当时你开发项目时的个性化配置,其中会包括编辑器的颜色、代码上传时自动压缩等等一系列选项。

3.页面配置page.json

给每个页面的.json文件进行配置,但是页面只能配置窗口的表现。页面的配置比app.json全局配置简单的多,只是设置app.json中的window配置项的内容,页面中配置项会覆盖app.json的window中相同的配置项。

4.WXML模板

相当于网页编程的WXML

5.WXSS模板

相当于网页编程的CSS样式

6.JS 交互逻辑

在小程序里边,我们就通过编写 JS 脚本文件来处理用户的操作。

6.项目目录结构

二.小程序配置

1.app.json

 

Copy:

{

"pages": [

"pages/index/index",

"pages/logs/logs",

"pages/menu/menu",

"pages/my/my"

],

"window": {

"backgroundColor": "#ff00ff",

"backgroundTextStyle": "light",

"navigationBarBackgroundColor": "#fc0",

"navigationBarTitleText": "东坡酒楼",

"navigationBarTextStyle": "black",

"enablePullDownRefresh": true

},

"tabBar": {

"color": "#fff",

"selectedColor": "#999",

"borderStyle": "white",

"position": "bottom",

"list": [

{

"pagePath": "pages/index/index",

"text": "主页",

"iconPath": "/images/1.png",

"selectedIconPath": "/images/1.1.png"

},

{

"pagePath": "pages/menu/menu",

"text": "点菜",

"iconPath": "/images/2.png",

"selectedIconPath": "/images/2.1.png"

},

{

"pagePath": "pages/my/my",

"text": "下单",

"iconPath": "/images/3.png",

"selectedIconPath": "/images/3.1.png"

}

]

}

}

 

 

Explain:app.json中不支持注释

{

"pages":[

"pages/index/index",   //导入页面

"pages/logs/logs",

"pages/menu/menu",

"pages/my/my"

],

"window":{

"backgroundColor":"#ff00ff",                 //窗口背景颜色

"backgroundTextStyle":"light",              //下拉加载的样式  dark/light

"navigationBarBackgroundColor": "#fc0",   //顶部标题背景颜色

"navigationBarTitleText": "东坡酒楼",     //顶部标题

"navigationBarTextStyle":"black",       //顶部标题颜色  black/white

"enablePullDownRefresh": true          //是否开启下拉刷新

},

"tabBar": {                   //导航条 

"color":"#fff",              //导航条文字颜色

"selectedColor":"#999",     //导航条文字被选中后的颜色

"borderStyle":"white",     //导航条上边框的颜色  black/white

"position":"bottom",       //导航条位置  bottom/top  top时无图标,有下边框

 

"list": [{

"pagePath": "pages/index/index",         //导航条链接页面

"text": "主页",                           //导航条文字

"iconPath": "/images/1.png",            //导航条图片

"selectedIconPath": "/images/1.1.png"  //导航条被选中后的图片

},{

"pagePath": "pages/menu/menu",        

"text": "点菜",

"iconPath": "/images/2.png",

"selectedIconPath": "/images/2.1.png"

},{

"pagePath": "pages/my/my",

"text": "下单",

"iconPath": "/images/3.png",

"selectedIconPath": "/images/3.1.png"

}]

}

}

 

10.页面上拉触底事件触发时距页面底部距离:onReachBottomDistance:50  单位为px

11.页面整体上下滚动:disableScroll:设置为 true 则页面整体不能上下滚动;只在 page.json 中有效,无法在 app.json 中设置该项

 

2. Wxml

1.基础

1.text文本

属性space显示连续空格:ensp中文字符空格的一半、emsp中文字符空格大小

属性decode="true" ,转化特殊字符:  < > & '  

例:<text space='ensp' decode="true" selectable='true' class="text1" > 1> 1 1 </text>

 

 

2.icon图标

属性type图标类型success, success_no_circle, info, warn, waiting, cancel, download, search, clear

 

属性size图标大小,单位px,不用加

属性color图标颜色:支持英文颜色和16进制颜色

例:<icon type="info" size="40" color="#ff00ff" />

 

 

3.progress进度条

属性:percent进度,百分比0~100

show-info在进度条右侧显示百分比

stroke-width  进度条线的宽度,单位px

Color 进度条颜色 (请使用 activeColor) 

activeColor  已选择的进度条的颜色

backgroundColor  未选择的进度条的颜色

active  进度条从左往右的动画

例:<progress percent="20" show-info />

<progress percent="40" stroke-width="12" />

<progress percent="60" color="pink" />

<progress percent="80" active />

 

2.表单组件

1.button按钮

属性:size按钮大小

type按钮类型

plain按钮是否镂空

Disabled是否禁用

Loading是否带loading图标

Form-type用于<from/>组建,点击出发submit/reset事件

App-parameter打开app时,向app传递的参数

Hover-class按钮按下去的样式类

send-message-path 会话内消息卡片点击跳转小程序路径

send-message-img 会话内消息卡片图片

Bindgetphonenumber  获取用户手机号回调

Binderror  当使用开放能力时,发生错误的回调

例:<button type="primary" size="{{primarySize}}" loading="{{loading}}" plain="{{plain}}"

disabled="{{disabled}}" bindtap="primary"> primary </button>

 

2.checkbox多选框

<checkbox-group bindchange="checkboxChange">

<label class="checkbox" wx:for="{{items}}">

<checkbox value="{{item.name}}" checked="true"/>{{item.value}}

</label>

</checkbox-group>

 

Js中:Page({

  data: {

    items: [

      {name: 'USA', value: '美国'},

      {name: 'CHN', value: '中国', checked: 'true'},

      {name: 'BRA', value: '巴西'},

      {name: 'JPN', value: '日本'},

      {name: 'ENG', value: '英国'},

      {name: 'TUR', value: '法国'},

    ]

  },

  checkboxChange: function(e) {

    console.log('checkbox发生change事件,携带value值为:', e.detail.value)

  }

})

 

3.form表单

<form bindsubmit="formSubmit" bindreset="formReset">

<view class="section section_gap">

<view class="section__title">switch</view>

<switch name="switch"/>

</view>

<view class="section section_gap">

<view class="section__title">slider</view>

<slider name="slider" show-value ></slider>

</view> 

<view class="section">

<view class="section__title">input</view>

<input name="input" placeholder="please input here" />

</view>

<view class="section section_gap">

<view class="section__title">radio</view>

<radio-group name="radio-group">

<label><radio value="radio1"/>radio1</label>

<label><radio value="radio2"/>radio2</label>

</radio-group>

</view>

<view class="section section_gap">

<view class="section__title">checkbox</view>

<checkbox-group name="checkbox">

<label><checkbox value="checkbox1"/>checkbox1</label>

<label><checkbox value="checkbox2"/>checkbox2</label>

</checkbox-group>

</view>

<view class="btn-area">

<button formType="submit">Submit</button>

<button formType="reset">Reset</button>

</view>

</form>

 

Js控制:

Page({

  formSubmit: function(e) {

    console.log('form发生了submit事件,携带数据为:', e.detail.value)

  },

  formReset: function() {

    console.log('form发生了reset事件')

  }

})

 

4.input

Value    输入框的初始内容

type    input 的类型

Text 文本输入键盘

Number 数字输入键盘

Idcard 身份证输入键盘

Digit 带小数点的数字键盘

password   是否是密码类型

placeholder   输入框为空时占位符,提示文字

placeholder-style  指定 placeholder 的样式

Disabled   是否禁用

maxlength  最大输入长度,设置为 -1 的时候不限制最大长度

cursor-spacing  指定光标与键盘的距离,单位 px 。取 input 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离

focus  获取焦点

confirm-type  设置键盘右下角按钮的文字

Send 右下角按钮为“发送”

Search 右下角按钮为“搜索”

Next 右下角按钮为“下一个”

Go 右下角按钮为“前往”

Done 右下角按钮为“完成” 

confirm-hold  点击键盘右下角按钮时是否保持键盘不收起

adjust-position  键盘弹起时,是否自动上推页面

bindinput  当键盘输入时,触发input事件,event.detail = {value, cursor},处理函数可以直接 return 一个字符串,将替换输入框的内容。

bindfocus   输入框聚焦时触发,event.detail = { value, height },height 为键盘高度,在基础库 1.9.90 起支持

bindblur   输入框失去焦点时触发,event.detail = {value: value}

bindconfirm  点击完成按钮时触发,event.detail = {value: value}

 

 

5.picker选择器

<view class="section">

  <view class="section__title">普通选择器</view>

  <picker bindchange="bindPickerChange" value="{{index}}" range="{{array}}">

    <view class="picker">

      当前选择:{{array[index]}}

    </view>

  </picker></view><view class="section">

  <view class="section__title">多列选择器</view>

  <picker mode="multiSelector" bindchange="bindMultiPickerChange" bindcolumnchange="bindMultiPickerColumnChange" value="{{multiIndex}}" range="{{multiArray}}">

    <view class="picker">

      当前选择:{{multiArray[0][multiIndex[0]]}},{{multiArray[1][multiIndex[1]]}},{{multiArray[2][multiIndex[2]]}}

    </view>

  </picker></view><view class="section">

  <view class="section__title">时间选择器</view>

  <picker mode="time" value="{{time}}" start="09:01" end="21:01" bindchange="bindTimeChange">

    <view class="picker">

      当前选择: {{time}}

    </view>

  </picker></view>

<view class="section">

  <view class="section__title">日期选择器</view>

  <picker mode="date" value="{{date}}" start="2015-09-01" end="2017-09-01" bindchange="bindDateChange">

    <view class="picker">

      当前选择: {{date}}

    </view>

  </picker></view><view class="section">

  <view class="section__title">省市区选择器</view>

  <picker mode="region" bindchange="bindRegionChange" value="{{region}}" custom-item="{{customItem}}">

    <view class="picker">

      当前选择:{{region[0]}},{{region[1]}},{{region[2]}}

    </view>

  </picker></view>

 

Js

Page({

  data: {

    array: ['美国', '中国', '巴西', '日本'],

    objectArray: [

      { id: 0,   name: '美国'   },

      { id: 1,   name: '中国'   },

      { id: 2,   name: '巴西'   },

      { id: 3,   name: '日本'   }

    ],

    index: 0,

    multiArray: [['无脊柱动物', '脊柱动物'], ['扁性动物', '线形动物', '环节动物', '软体动物', '节肢动物'], ['猪肉绦虫', '吸血虫']],

    objectMultiArray: [

      [

        {  id: 0,    name: '无脊柱动物'  },

        {  id: 1,    name: '脊柱动物'    }

      ], [

        { id: 0,  name: '扁性动物'   },

        { id: 1,  name: '线形动物'   },

        { id: 2,  name: '环节动物'   },

        { id: 3,  name: '软体动物'   },

        { id: 3,  name: '节肢动物'   }

      ], [

        { id: 0,  name: '猪肉绦虫'  },

        { id: 1,  name: '吸血虫'  }

      ]

    ],

    multiIndex: [0, 0, 0],

    date: '2016-09-01',

    time: '12:01',

    region: ['广东省', '广州市', '海珠区'],

    customItem: '全部'

  },

  bindPickerChange: function(e) {

    console.log('picker发送选择改变,携带值为', e.detail.value)

    this.setData({

      index: e.detail.value

    })

  },

  bindMultiPickerChange: function (e) {

    console.log('picker发送选择改变,携带值为', e.detail.value)

    this.setData({

      multiIndex: e.detail.value

    })

  },

  bindMultiPickerColumnChange: function (e) {

    console.log('修改的列为', e.detail.column, ',值为', e.detail.value);

    var data = {

      multiArray: this.data.multiArray,

      multiIndex: this.data.multiIndex

    };

    data.multiIndex[e.detail.column] = e.detail.value;

    switch (e.detail.column) {

      case 0:

        switch (data.multiIndex[0]) {

          case 0:

            data.multiArray[1] = ['扁性动物', '线形动物', '环节动物', '软体动物', '节肢动物'];

            data.multiArray[2] = ['猪肉绦虫', '吸血虫'];

            break;

          case 1:

            data.multiArray[1] = ['鱼', '两栖动物', '爬行动物'];

            data.multiArray[2] = ['鲫鱼', '带鱼'];

            break;

        }

        data.multiIndex[1] = 0;

        data.multiIndex[2] = 0;

        break;

      case 1:

        switch (data.multiIndex[0]) {

          case 0:

            switch (data.multiIndex[1]) {

              case 0:

                data.multiArray[2] = ['猪肉绦虫', '吸血虫'];

                break;

              case 1:

                data.multiArray[2] = ['蛔虫'];

                break;

              case 2:

                data.multiArray[2] = ['蚂蚁', '蚂蟥'];

                break;

              case 3:

                data.multiArray[2] = ['河蚌', '蜗牛', '蛞蝓'];

                break;

              case 4:

                data.multiArray[2] = ['昆虫', '甲壳动物', '蛛形动物', '多足动物'];

                break;

            }

            break;

          case 1:

            switch (data.multiIndex[1]) {

              case 0:

                data.multiArray[2] = ['鲫鱼', '带鱼'];

                break;

              case 1:

                data.multiArray[2] = ['青蛙', '娃娃鱼'];

                break;

              case 2:

                data.multiArray[2] = ['蜥蜴', '龟', '壁虎'];

                break;

            }

            break;

        }

        data.multiIndex[2] = 0;

        console.log(data.multiIndex);

        break;

    }

    this.setData(data);

  },

  bindDateChange: function(e) {

    console.log('picker发送选择改变,携带值为', e.detail.value)

    this.setData({

      date: e.detail.value

    })

  },

  bindTimeChange: function(e) {

    console.log('picker发送选择改变,携带值为', e.detail.value)

    this.setData({

      time: e.detail.value

    })

  },

  bindRegionChange: function (e) {

    console.log('picker发送选择改变,携带值为', e.detail.value)

    this.setData({

      region: e.detail.value

    })

  }

})

 

 

 

 

 

 

 

普通选择器:mode = selector

 

多列选择器:mode = multiSelector

 

时间选择器:mode = time   

属性 value选中的时间,格式为hh:mm   start表示有效的时间范围的开始,格式hh::mm

end表示有效的时间范围的结束,格式hh::mm

bindchange改变时触发 change 事件,event.detail = {value: value}

bindcancel取消选择时触发

 

日期选择器:mode = date

除了上述的属性还有fields属性

Year 选择器粒度为年

Month 选择器粒度为月份

Day 选择器粒度为天

 

省市区选择器:mode = regionvalue

Array 表示选中的省市区,默认选中每一列的第一个值

custom-item可为每一列的顶部添加一个自定义的项

Bindchange   value 改变时触发 change 事件,event.detail = {value: value}

Bindcancel  取消选择时触发

disabled 是否禁用

 

 

 

6. slider滑动选择器

<view class="section section_gap">

  <text class="section__title">设置step</text>

  <view class="body-view">

    <slider bindchange="slider2change" step="5"/>

  </view></view>

<view class="section section_gap">

  <text class="section__title">显示当前value</text>

  <view class="body-view">

    <slider bindchange="slider3change" show-value/>

  </view></view>

<view class="section section_gap">

  <text class="section__title">设置最小/最大值</text>

  <view class="body-view">

    <slider bindchange="slider4change" min="50" max="200" show-value/>

  </view></view>

 

Js

var pageData = {}for (var i = 1; i < 5; i++) {

  (function (index) {

    pageData['slider' + index + 'change'] = function(e) {

      console.log('slider' + 'index' + '发生 change 事件,携带值为', e.detail.value)

    }

  })(i)

}

Page(pageData)

 

min  最小值

max 最大值

step步长,取值必须大于 0,并且可被(max - min)整除

disabled是否禁用

value当前取值

color背景条的颜色(请使用 backgroundColor

selected-color已选择的颜色(请使用 activeColor

activeColor已选择的颜色

backgroundColor背景条的颜色

block-size滑块的大小,取值范围为 12 - 28

block-color滑块的颜色

show-value是否显示当前 value

bindchange完成一次拖动后触发的事件,event.detail = {value: value}

bindchanging拖动过程中触发的事件,event.detail = {value: value}

 

7.switch开关选择器

<view class="body-view">

    <switch checked bindchange="switch1Change"/>

<switch bindchange="switch2Change"/></view>

Js中:

Page({

  switch1Change: function (e){

    console.log('switch1 发生 change 事件,携带值为', e.detail.value)

  },

  switch2Change: function (e){

    console.log('switch2 发生 change 事件,携带值为', e.detail.value)

  }

})

 

checked 

是否选中

type样式,有效值:switch, checkbox

Bindchange   checked 改变时触发 change 事件,event.detail={ value:checked}

Color  switch 的颜色,同 css color

 

 

7. navigator导航

/** wxss **//** 修改默认的navigator点击态 **/.navigator-hover {

    color:blue;

}/** 自定义其他点击态样式类 **/.other-navigator-hover {

    color:red;

}

 

<!-- sample.wxml --><view class="btn-area">

  <navigator url="/page/navigate/navigate?title=navigate" hover-class="navigator-hover">跳转到新页面</navigator>

  <navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">在当前页打开</navigator>

  <navigator url="/page/index/index" open-type="switchTab" hover-class="other-navigator-hover">切换 Tab</navigator></view>

 

<!-- navigator.wxml -->

<view style="text-align:center"> {{title}} </view><view> 点击左上角返回回到之前页面 </view>

 

<!-- redirect.wxml -->

<view style="text-align:center"> {{title}} </view><view> 点击左上角返回回到上级页面 </view>

 

// redirect.js navigator.js

Page({

  onLoad: function(options) {

    this.setData({

      title: options.title

    })

  }

})

url 应用内的跳转链接

open-type redirect/switchTab/reLaunch/navigateBack跳转方式

delta  open-type 'navigateBack' 时有效,表示回退的层数

hover-class: navigator-hover 指定点击时的样式类,当hover-class="none"时,没有点击态效果

hover-stop-propagation 指定是否阻止本节点的祖先节点出现点击态

 

3.媒体组件

1. audio音频

·<!-- audio.wxml -->

<audio poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{src}}" id="myAudio" controls loop></audio>

<button type="primary" bindtap="audioPlay">播放</button>

<button type="primary" bindtap="audioPause">暂停</button>

<button type="primary" bindtap="audio14">设置当前播放时间为14秒</button>

<button type="primary" bindtap="audioStart">回到开头</button>

Js中:

// audio.js

Page({

  onReady: function (e) {

    // 使用 wx.createAudioContext 获取 audio 上下文 context

    this.audioCtx = wx.createAudioContext('myAudio')

  },

  data: {

    poster: 'http://y.gtimg.cn/music/photo_new/T002R300x300M000003rsKF44GyaSk.jpg?max_age=2592000',

    name: '此时此刻',

    author: '许巍',

    src: 'http://ws.stream.qqmusic.qq.com/M500001VfvsJ21xFqb.mp3?guid=ffffffff82def4af4b12b3cd9337d5e7&uin=346897220&vkey=6292F51E1E384E06DCBDC9AB7C49FD713D632D313AC4858BACB8DDD29067D3C601481D36E62053BF8DFEAF74C0A5CCFADD6471160CAF3E6A&fromtag=46',

  },

  audioPlay: function () {

    this.audioCtx.play()

  },

  audioPause: function () {

    this.audioCtx.pause()

  },

  audio14: function () {

    this.audioCtx.seek(14)

  },

  audioStart: function () {

    this.audioCtx.seek(0)

  }

})

id audio 组件的唯一标识符

src要播放音频的资源地址

loop:false是否循环播放

controls:false是否显示默认控件

poster默认控件上的音频封面的图片资源地址,如果 controls 属性值为 false 则设置 poster 无效

name默认控件上的音频名字,如果 controls 属性值为 false 则设置 name 无效

author默认控件上的作者名字,如果 controls 属性值为 false 则设置 author 无效

binderror当发生错误时触发 error 事件,detail = {errMsg: MediaError.code}

bindplay当开始/继续播放时触发play事件

bindpause当暂停播放时触发 pause 事件

bindtimeupdate当播放进度改变时触发 timeupdate 事件,detail = {currentTime, duration}

bindended当播放到末尾时触发 ended 事件

2. Video视频

<view class="section tc">

  <video src="{{src}}"   controls ></video>

  <view class="btn-area">

    <button bindtap="bindButtonTap">获取视频</button>

  </view></view>

<view class="section tc">

  <video id="myVideo" src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" danmu-list="{{danmuList}}" enable-danmu danmu-btn controls></video>

  <view class="btn-area">

    <button bindtap="bindButtonTap">获取视频</button>

    <input bindblur="bindInputBlur"/>

    <button bindtap="bindSendDanmu">发送弹幕</button>

  </view></view>

 

Js中:

function getRandomColor () {

  let rgb = []

  for (let i = 0 ; i < 3; ++i){

    let color = Math.floor(Math.random() * 256).toString(16)

    color = color.length == 1 ? '0' + color : color

    rgb.push(color)

  }

  return '#' + rgb.join('')

} 

Page({

  onReady: function (res) {

    this.videoContext = wx.createVideoContext('myVideo')

  },

  inputValue: '',

    data: {

        src: '',

    danmuList: [

      { text: '第 1s 出现的弹幕',  color: '#ff0000',  time: 1  },

      { text: '第 3s 出现的弹幕',  color: '#ff00ff',  time: 3  }]

    },

  bindInputBlur: function(e) {

    this.inputValue = e.detail.value

  },

  bindButtonTap: function() {

    var that = this

    wx.chooseVideo({

      sourceType: ['album', 'camera'],

      maxDuration: 60,

      camera: ['front','back'],

      success: function(res) {

        that.setData({

          src: res.tempFilePath

        })

      }

    })

  },

  bindSendDanmu: function () {

    this.videoContext.sendDanmu({

      text: this.inputValue,

      color: getRandomColor()

    })

  }

})

 

src要播放视频的资源地址

initial-time:Number 指定视频初始播放位置

duration:Number 指定视频时长

Controls : true 是否显示默认播放控件(播放/暂停按钮、播放进度、时间)

danmu-list:弹幕列表

danmu-btn:false 是否显示弹幕按钮,只在初始化时有效,不能动态变更

enable-danmu:false 是否展示弹幕,只在初始化时有效,不能动态变更

autoplay:false 是否自动播放

loop:false 是否循环播放

muted:false 是否静音播放

page-gesture:false 在非全屏模式下,是否开启亮度与音量调节手势

Direction:Number设置全屏时视频的方向,不指定则根据宽高比自动判断。有效值为 0(正常竖向), 90(屏幕逆时针90度), -90(屏幕顺时针90度)

show-progress:true 若不设置,宽度大于240时才会显示

show-fullscreen-btn:true 是否显示全屏按钮

show-play-btn:true 是否显示视频底部控制栏的播放按钮

show-center-play-btn:true 是否显示视频中间的播放按钮

enable-progress-gesture:true 是否开启控制进度的手势

objectFit:contain当视频大小与 video 容器大小不一致时,视频的表现形式。contain:包含,fill:填充,cover:覆盖

poster:视频封面的图片网络资源地址,如果 controls 属性值为 false 则设置 poster 无效

Bindplay:当开始/继续播放时触发play事件

bindpause:当暂停播放时触发 pause 事件

bindended:当播放到末尾时触发 ended 事件

bindtimeupdate:播放进度变化时触发,event.detail = {currentTime, duration} 。触发频率 250ms 一次

bindfullscreenchange:当视频进入和退出全屏是触发,event.detail = {fullScreen, direction},direction取为 vertical 或 horizontal

bindwaiting:视频出现缓冲时触发

binderror:视频播放出错时触发

 

 

3. Camera相机

<!-- camera.wxml -->

<camera device-position="back" flash="off" binderror="error" style="width: 100%; height: 300px;"></camera>

<button type="primary" bindtap="takePhoto">拍照</button>

<view>预览</view>

<image mode="widthFix" src="{{src}}"></image>

 

JS

// camera.js

Page({

    takePhoto() {

        const ctx = wx.createCameraContext()

        ctx.takePhoto({

            quality: 'high',

            success: (res) => {

                this.setData({

                    src: res.tempImagePath

                })

            }

        })

    },

    error(e) {

        console.log(e.detail)

    }

})

 

device-position 前置或后置,值为front, back

flash 闪光灯,值为auto, on, off

bindstop 摄像头在非正常终止时触发,如退出后台等情况

binderror用户不允许使用摄像头时触发

 

 

4. Image图片

<image style="width: 200px; height: 200px; background-color: #eeeeee;" mode="{{item.mode}}" src="{{src}}"></image>

src 图片资源地址

mode:'scaleToFill' 图片裁剪、缩放的模式

缩放 scaleToFill 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素

缩放 aspectFit 保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。

缩放 aspectFill 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。

缩放 widthFix 宽度不变,高度自动变化,保持原图宽高比不变

裁剪 top 不缩放图片,只显示图片的顶部区域

裁剪 bottom 不缩放图片,只显示图片的底部区域

裁剪 center 不缩放图片,只显示图片的中间区域

裁剪 left 不缩放图片,只显示图片的左边区域

裁剪 right 不缩放图片,只显示图片的右边区域

裁剪 top left 不缩放图片,只显示图片的左上边区域

裁剪 top right 不缩放图片,只显示图片的右上边区域

裁剪 bottom left 不缩放图片,只显示图片的左下边区域

裁剪 bottom right 不缩放图片,只显示图片的右下边区域

binderror:当错误发生时,发布到 AppService 的事件名,事件对象event.detail = {errMsg: 'something wrong'}

bindload:当图片载入完毕时,发布到 AppService 的事件名,事件对象event.detail = {height:'图片高度px', width:'图片宽度px'}

4.网络

1.request请求

onShow:function(){

var that = this

wx.request({

url: 'http://127.0.0.1:8080/tankWeb/dishInfo/dish/select.dhtml', //仅为示例,并非真实的接口地址

method:'POST',

data: { },

header: {

'content-type': 'application/x-www-form-urlencoded' // 默认值

},

dataType: "JSON",

arraybuffer: "arrayBuffer",

success: function (res) {

var jtext = JSON.parse(res.data);//将字符转转为数组、对象

wx.setStorageSync("dishList", jtext);

that.setData({

dishList: jtext

})

}

})

三.逻辑层

1.注册程序App()

1.App()

App() 函数用来注册一个小程序。接受一个 object 参数,其指定小程序的生命周期函数等。

示例代码:

App({

  onLaunch: function(options) {

// 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)  

},

  onShow: function(options) {

      // 当小程序启动,或从后台进入前台显示,会触发 onShow.

  },

  onHide: function() {

      // 当小程序从前台进入后台,会触发 onHide.

  },

  onError: function(msg) {

console.log(msg)

//当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息

  },

  globalData: 'I am global data'

})

5.当小程序出现要打开的页面不存在的情况,会带上页面信息回调该函数,详见下文: onPageNotFound

6.开发者可以添加任意的函数或数据到 Object 参数中,用 this 可以访问

3.onLaunch, onShow 参数

1.打开小程序的路径:path:String

2.打开小程序的queryquery:Object

3.打开小程序的场景值:scene:Number

4.获取更多转发信息: shareTicket:String

5.当场景为由从另一个小程序或公众号或App打开时,返回此字段:referrerInfo:Object

6.来源小程序传过来的数据,scene=10371038时支持:referrerInfo.extraData:Object

7.来源小程序或公众号或AppappId:referrerInfo.appId:String

 

2.场景值

1001    发现栏小程序主入口

1005    顶部搜索框的搜索结果页

1006 发现栏小程序主入口搜索框的搜索结果页

1007 单人聊天会话中的小程序消息卡片

1008 群聊会话中的小程序消息卡片

1011 扫描二维码

1012 长按图片识别二维码

1013 手机相册选取二维码

1014 小程序模版消息

1017 前往体验版的入口页

1019 微信钱包

1020 公众号 profile 页相关小程序列表

1022 聊天顶部置顶小程序入口

1023 安卓系统桌面图标

1024 小程序 profile

1025 扫描一维码

1026 附近小程序列表

1027  顶部搜索框搜索结果页使用过的小程序列表

1028 我的卡包

1029 卡券详情页

1030 自动化测试下打开小程序

1031 长按图片识别一维码

1032 手机相册选取一维码

1034 微信支付完成页

1035 公众号自定义菜单

1036 App 分享消息卡片

1037 小程序打开小程序

1038 从另一个小程序返回

1039 摇电视

1042 添加好友搜索框的搜索结果页

1043 公众号模板消息

1044 带 shareTicket 的小程序消息卡片(详情)

1047 扫描小程序码

1048 长按图片识别小程序码

1049 手机相册选取小程序码

1052 卡券的适用门店列表

1053 搜一搜的结果页

1054 顶部搜索框小程序快捷入口

1056 音乐播放器菜单

1057 钱包中的银行卡详情页

1058 公众号文章

1059 体验版小程序绑定邀请页

1064 微信连Wi-Fi状态栏

1067 公众号文章广告

1068 附近小程序列表广告

1071 钱包中的银行卡列表页

1072 二维码收款页面

1073 客服消息列表下发的小程序消息卡片

1074 公众号会话下发的小程序消息卡片

1078 连Wi-Fi成功页

1089 微信聊天主界面下拉

1090 长按小程序右上角菜单唤出最近使用历史

1092 城市服务入口 

 

3.注册页面Page()

1.Page() 

Page() 函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。

object 内容在页面加载时会进行一次深拷贝,需考虑数据大小对页面加载的开销

示例代码:

//index.js

Page({

  data: {

text: "This is page data."

//.页面的初始数据: data:Object  

  },

  onLoad: function(options) {

// 生命周期函数--监听页面加载onLoad:Function

  },

  onReady: function() {

    // 生命周期函数--监听页面初次渲染完成onReady:Function 

  },

  onShow: function() {

    //生命周期函数--监听页面显示onShow:Function 

  },

  onHide: function() {

    // 生命周期函数--监听页面隐藏:onHide:Function  },

  onUnload: function() {

    // 生命周期函数--监听页面卸载onUnload:Function 

  },

  onPullDownRefresh: function() {

    // 页面相关事件处理函数--监听用户下拉动作onPullDownRefresh:Function 

  },

  onReachBottom: function() {

// 页面上拉触底事件的处理函数:onReachBottom:Function 

  },

  onShareAppMessage: function () {

   // 用户点击右上角转发onShareAppMessage:Function 

  },

  onPageScroll: function() {

    // 页面滚动触发事件的处理函数onPageScroll:Function 

  },

  onTabItemTap(item) {

当前是 tab 页时,点击 tab 时触发onTabItemTap:Function 

 

    console.log(item.index)

    console.log(item.pagePath)

    console.log(item.text)

  },

  // Event handler.

  viewTap: function() {

    this.setData({

      text: 'Set some data for updating view.'

    }, function() {

      // this is setData callback

    })

  },

  customData: {

    hi: 'MINA'

  }

})

2.初始化数据

初始化数据将作为页面的第一次渲染。data 将会以 JSON 的形式由逻辑层传至渲染层,所以其数据必须是可以转成 JSON 的格式:字符串,数字,布尔值,对象,数组。 渲染层可以通过 WXML 对数据进行绑定。

示例代码:

<view>{{text}}</view><view>{{array[0].msg}}</view>

Page({

  data: {

    text: 'init data',

    array: [{msg: '1'}, {msg: '2'}]

  }

})

4.页面相关事件处理函数

1.下拉刷新:onPullDownRefresh 监听用户下拉刷新事件。需要在app.jsonwindow选项中或页面配置中开启enablePullDownRefresh 当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。

2.上拉触底:onReachBottom  监听用户上拉触底事件。 可以在app.jsonwindow选项中或页面配置中设置触发距离onReachBottomDistance 在触发距离内滑动期间,本事件只会被触发一次。

3.页面滚动: onPageScroll:  监听用户滑动页面事件。 参数为 Object,包含以下字段:

scrollTop:Number 页面在垂直方向已滚动的距离(单位px

4.用户转发: onShareAppMessage 只有定义了此事件处理函数,右上角菜单才会显示转发按钮,用户点击转发按钮的时候会调用,此事件需要 return 一个 Object,用于自定义转发内容,自定义转发字段:

转发标题:title 当前小程序名称

转发路径:path 当前页面 path ,必须是以 / 开头的完整路径

示例代码

Page({

  onShareAppMessage: function () {

    return {

      title: '自定义转发标题',

      path: '/page/user?id=123'

    }

  }

})

5.事件处理函数

除了初始化数据和生命周期函数,Page 中还可以定义一些特殊的函数:事件处理函数。在渲染层可以在组件中加入事件绑定,当达到触发事件时,就会执行 Page 中定义的事件处理函数。

示例代码:

<view bindtap="viewTap"> click me </view>

Page({

  viewTap: function() {

    console.log('view tap')

  }

})

1.Page.prototype.route route 字段可以获取到当前页面的路径。

2.Page.prototype.setData():setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。

setData() 参数格式

1.dataObject 这次要改变的数据  

2.callback:Function 回调函数

 object 以 key,value 的形式表示将 this.data 中的 key 对应的值改变成 value。 callback 是一个回调函数,在这次setData对界面渲染完毕后调用。其中 key 可以非常灵活,以数据路径的形式给出,如 array[2].messagea.b.c.d,并且不需要在 this.data 中预先定义。

注意:

直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据 请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题。

示例代码:

<!--index.wxml--><view>{{text}}</view><button bindtap="changeText"> Change normal data </button><view>{{num}}</view><button bindtap="changeNum"> Change normal num </button><view>{{array[0].text}}</view><button bindtap="changeItemInArray"> Change Array data </button><view>{{object.text}}</view><button bindtap="changeItemInObject"> Change Object data </button><view>{{newField.text}}</view><button bindtap="addNewField"> Add new data </button>

//index.js

Page({

  data: {

    text: 'init data',

    num: 0,

    array: [{text: 'init data'}],

    object: {

      text: 'init data'

    }

  },

  changeText: function() {

    // this.data.text = 'changed data'  // bad, it can not work

    this.setData({

      text: 'changed data'

    })

  },

  changeNum: function() {

    this.data.num = 1

    this.setData({

      num: this.data.num

    })

  },

  changeItemInArray: function() {

    // you can use this way to modify a danamic data path

    this.setData({

      'array[0].text':'changed data'

    })

  },

  changeItemInObject: function(){

    this.setData({

      'object.text': 'changed data'

    });

  },

  addNewField: function() {

    this.setData({

      'newField.text': 'new data'

    })

  }

})

6.Page()实例的生命周期

下图说明了 Page 实例的生命周期。

4.文件作用域

JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。

通过全局函数 getApp() 可以获取全局的应用实例,如果需要全局的数据可以在 App() 中设置,如:

// app.js

App({

  globalData: 1

})

// a.js// The localValue can only be used in file a.js.var localValue = 'a'// Get the app instance.var app = getApp()// Get the global data and change it.

app.globalData++

// b.js// You can redefine localValue in file b.js, without interference with the localValue in a.js.var localValue = 'b'// If a.js it run before b.js, now the globalData shoule be 2.console.log(getApp().globalData)

5.模块化

可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。

需要注意的是:

exports  module.exports 的一个引用,因此在模块里边随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用 module.exports来暴露模块接口,除非你已经清晰知道这两者的关系。

小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中。

// common.js

function sayHello(name) {

  console.log(`Hello ${name} !`)

}function sayGoodbye(name) {

  console.log(`Goodbye ${name} !`)

}

module.exports.sayHello = sayHello

exports.sayGoodbye = sayGoodbye

在需要使用这些模块的文件中,使用 require(path) 将公共代码引入

var common = require('common.js')

Page({

  helloMINA: function() {

    common.sayHello('MINA')

  },

  goodbyeMINA: function() {

    common.sayGoodbye('MINA')

  }

})

tip: require 暂时不支持绝对路径

四.视图层

1.wxml

1.数据绑定

简单绑定

数据绑定使用 Mustache 语法(双大括号)将变量包起来

<view> {{ message }} </view>

Page({

  data: {

    message: 'Hello MINA!'

  }

})

组件属性(需要在双引号之内)

<view id="item-{{id}}"> </view>

Page({

  data: {

    id: 0

  }

})

 

控制属性(需要在双引号之内)

<view wx:if="{{condition}}"> </view>

Page({

  data: {

    condition: true

  }

})

关键字(需要在双引号之内)

trueboolean 类型的 true,代表真值。

false boolean 类型的 false,代表假值。

<checkbox checked="{{false}}"> </checkbox>

特别注意:不要直接写 checked="false",其计算结果是一个字符串,转成 boolean 类型后代表真值。

 

运算

可以在 {{}} 内进行简单的运算,支持的有如下几种方式:

三元运算

<view hidden="{{flag ? true : false}}"> Hidden </view>

算数运算

<view> {{a + b}} + {{c}} + d </view>

Page({

  data: {

    a: 1,

    b: 2,

    c: 3

  }

})

view中的内容为 3 + 3 + d

逻辑判断

<view wx:if="{{length > 5}}"> </view>

字符串运算

<view>{{"hello" + name}}</view>

Page({

  data:{

    name: 'MINA'

  }

})

数据路径运算

<view>{{object.key}} {{array[0]}}</view>

Page({

  data: {

    object: {

      key: 'Hello '

    },

    array: ['MINA']

  }

})

 

组合

也可以在 Mustache 内直接进行组合,构成新的对象或者数组。

数组

<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>

Page({

  data: {

    zero: 0

  }

})

最终组合成数组[0, 1, 2, 3, 4]

对象

<template is="objectCombine" data="{{for: a, bar: b}}"></template>

Page({

  data: {

    a: 1,

    b: 2

  }

})

最终组合成的对象是 {for: 1, bar: 2}

也可以用扩展运算符 ... 来将一个对象展开

<template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template>

Page({

  data: {

    obj1: {

      a: 1,

      b: 2

    },

    obj2: {

      c: 3,

      d: 4

    }

  }

})

最终组合成的对象是 {a: 1, b: 2, c: 3, d: 4, e: 5}

如果对象的 key 和 value 相同,也可以间接地表达。

<template is="objectCombine" data="{{foo, bar}}"></template>

Page({

  data: {

    foo: 'my-foo',

    bar: 'my-bar'

  }

})

最终组合成的对象是 {foo: 'my-foo', bar:'my-bar'}

注意:上述方式可以随意组合,但是如有存在变量名相同的情况,后边的会覆盖前面,如:

<template is="objectCombine" data="{{...obj1, ...obj2, a, c: 6}}"></template>

Page({

  data: {

    obj1: {

      a: 1,

      b: 2

    },

    obj2: {

      b: 3,

      c: 4

    },

    a: 5

  }

})

最终组合成的对象是 {a: 5, b: 3, c: 6}

注意: 花括号和引号之间如果有空格,将最终被解析成为字符串

<view wx:for="{{[1,2,3]}} ">

  {{item}}</view>

等同于

<view wx:for="{{[1,2,3] + ' '}}">

  {{item}}</view>

2.列表渲染

wx:for

在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。

默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

<view wx:for="{{array}}">

  {{index}}: {{item.message}}</view>

Page({

  data: {

    array: [{

      message: 'foo',

    }, {

      message: 'bar'

    }]

  }

})

使用 wx:for-item 可以指定数组当前元素的变量名, 使用 wx:for-index 可以指定数组当前下标的变量名:

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">

  {{idx}}: {{itemName.message}}</view>

wx:for 也可以嵌套,下边是一个九九乘法表

<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i">

  <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">

    <view wx:if="{{i <= j}}">

      {{i}} * {{j}} = {{i * j}}

    </view>

  </view></view>

block wx:for

类似 block wx:if,也可以将 wx:for 用在<block/>标签上,以渲染一个包含多节点的结构块。例如:

<block wx:for="{{[1, 2, 3]}}">

  <view> {{index}}: </view>

  <view> {{item}} </view></block>

 

注意:

 wx:for 的值为字符串时,会将字符串解析成字符串数组

<view wx:for="array">

  {{item}}</view>

等同于

<view wx:for="{{['a','r','r','a','y']}}">

  {{item}}</view>

注意: 花括号和引号之间如果有空格,将最终被解析成为字符串

<view wx:for="{{[1,2,3]}} ">

  {{item}}</view>

等同于

<view wx:for="{{[1,2,3] + ' '}}" >

  {{item}}</view>

3.条件渲染

wx:if

在框架中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块:

<view wx:if="{{condition}}"> True </view>

也可以用 wx:elif 和 wx:else 来添加一个 else 块:

<view wx:if="{{length > 5}}"> 1 </view><view wx:elif="{{length > 2}}"> 2 </view><view wx:else> 3 </view>

block wx:if

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

<block wx:if="{{true}}">

  <view> view1 </view>

  <view> view2 </view></block>

4.模板

<!--wxml--><template name="staffName">

  <view>

    FirstName: {{firstName}}, LastName: {{lastName}}

  </view></template>

<template is="staffName" data="{{...staffA}}"></template><template is="staffName" data="{{...staffB}}"></template><template is="staffName" data="{{...staffC}}"></template>

// page.js

Page({

  data: {

    staffA: {firstName: 'Hulk', lastName: 'Hu'},

    staffB: {firstName: 'Shang', lastName: 'You'},

    staffC: {firstName: 'Gideon', lastName: 'Lin'}

  }

})

WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。

定义模板

使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,如:

<!-- index: int  msg: string  time: string -->

<template name="msgItem">

  <view>

    <text> {{index}}: {{msg}} </text>

    <text> Time: {{time}} </text>

  </view>

</template>

使用模板

使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入,如:

<template is="msgItem" data="{{...item}}"/>

Page({

  data: {

    item: {

      index: 0,

      msg: 'this is a template',

      time: '2016-09-15'

    }

  }

})

is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:

<template name="odd">

  <view> odd </view></template><template name="even">

  <view> even </view></template>

<block wx:for="{{[1, 2, 3, 4, 5]}}">

    <template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/></block>

模板的作用域

模板拥有自己的作用域,只能使用 data 传入的数据以及模版定义文件中定义的 <wxs /> 模块。

5.事件

什么是事件

事件是视图层到逻辑层的通讯方式。事件可以将用户的行为反馈到逻辑层进行处理。事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。事件对象可以携带额外信息,如 id, dataset, touches。

事件的使用方式

· 在组件中绑定一个事件处理函数。

bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。

<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>

· 在相应的Page定义中写上相应的事件处理函数,参数是event。

Page({

  tapName: function(event) {

    console.log(event)

  }

})

· 可以看到log出来的信息大致如下:

{"type":"tap","timeStamp":895,"target": {

  "id": "tapTest",

  "dataset":  {

    "hi":"WeChat"

  }

},"currentTarget":  {

  "id": "tapTest",

  "dataset": {

    "hi":"WeChat"

  }

},"detail": {

  "x":53,

  "y":14

},"touches":[{

  "identifier":0,

  "pageX":53,

  "pageY":14,

  "clientX":53,

  "clientY":14

}],"changedTouches":[{

  "identifier":0,

  "pageX":53,

  "pageY":14,

  "clientX":53,

  "clientY":14

}]

}

· 

事件分类

事件分为冒泡事件和非冒泡事件:

1. 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。

2. 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。

WXML的冒泡事件列表:

1.手指触摸动作开始touchstart

2.手指触摸后移动touchmove

3.手指触摸动作被打断,如来电提醒,弹窗touchcancel

4.手指触摸动作结束touchend

5.手指触摸后马上离开tap

6.手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,longpress

7.事件将不被触发tap

8.手指触摸后,超过350ms再离开(推荐使用longpress事件代替)longtap

9.会在 WXSS transition 或 wx.createAnimation 动画结束后触发transitionend

9.会在一个 WXSS animation 动画开始时触发animationstart

10.会在一个 WXSS animation 一次迭代结束时触发animationiteration

11.会在一个 WXSS animation 动画完成时触发animationend

12.在支持 3D Touch 的 iPhone 设备,重按时会触发touchforcechange

事件绑定和冒泡

事件绑定的写法同组件的属性,以 key、value 的形式。

· key 以bindcatch开头,然后跟上事件的类型,如bindtapcatchtouchstart。自基础库版本 1.5.0 起,bindcatch后可以紧跟一个冒号,其含义不变,如bind:tap、、catch:touchstart

· value 是一个字符串,需要在对应的 Page 中定义同名的函数。不然当触发事件的时候会报错。

bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。

如在下边这个例子中,点击 inner view 会先后调用handleTap3handleTap2(因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2,点击 outer view 会触发handleTap1

<view id="outer" bindtap="handleTap1">

  outer view

  <view id="middle" catchtap="handleTap2">

    middle view

    <view id="inner" bindtap="handleTap3">

      inner view

    </view>

  </view></view>

事件的捕获阶段

自基础库版本 1.5.0 起,触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bindcapture-catch关键字,后者将中断捕获阶段和取消冒泡阶段。

在下面的代码中,点击 inner view 会先后调用handleTap2handleTap4handleTap3handleTap1

<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">

  outer view

  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">

    inner view

  </view></view>

如果将上面代码中的第一个capture-bind改为capture-catch,将只触发handleTap2

<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">

  outer view

  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">

    inner view

  </view></view>

6.引用

WXML 提供两种文件引用方式importinclude

import

import可以在该文件中使用目标文件定义的template,如:

item.wxml 中定义了一个叫itemtemplate

<!-- item.wxml --><template name="item">

  <text>{{text}}</text></template>

index.wxml 中引用了 item.wxml,就可以使用item模板:

<import src="item.wxml"/><template is="item" data="{{text: 'forbar'}}"/>

import 的作用域

import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template。

如:C import B,B import A,在C中可以使用B定义的template,在B中可以使用A定义的template,但是C不能使用A定义的template

<!-- A.wxml --><template name="A">

  <text> A template </text></template>

<!-- B.wxml --><import src="a.wxml"/><template name="B">

  <text> B template </text></template>

<!-- C.wxml --><import src="b.wxml"/><template is="A"/>  

<!-- Error! Can not use tempalte when not import A. --><template is="B"/>

include

include 可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置,如:

<!-- index.wxml --><include src="header.wxml"/><view> body </view><include src="footer.wxml"/>

<!-- header.wxml --><view> header </view>

<!-- footer.wxml --><view> footer </view>

2.WXS

WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

1.注释

WXS 主要有 3 种注释的方法。

示例代码:

<!-- wxml --><wxs module="sample">

// 方法一:单行注释

 

/*

方法二:多行注释

*/

 

/*

方法三:结尾注释。即从 /* 开始往后的所有 WXS 代码均被注释

上述例子中,所有 WXS 代码均被注释掉了。 方法三 方法二 的唯一区别是,没有 */ 结束符。

 

2.数据类型

number : 数值     string :字符串     boolean:布尔值     object:对象

function:函数     array : 数组       date:日期          regexp:正则

 

3.运算符

示例代码:

var a = 10, b = 20;

// 加法运算console.log(30 === a + b);// 减法运算console.log(-10 === a - b);// 乘法运算console.log(200 === a * b);// 除法运算console.log(0.5 === a / b);// 取余运算console.log(10 === a % b);

· 加法运算(+)也可以用作字符串的拼接。

var a = '.w' , b = 'xs';

// 字符串拼接console.log('.wxs' === a + b);

 

4.语句

if 语句

WXS 中,可以使用以下格式的 if 语句 :

if (expression) statement : 当 expression 为 truthy 时,执行 statement

if (expression) statement1 else statement2 : 当 expression 为 truthy 时,执行 statement1 否则,执行 statement2

if ... else if ... else statementN 通过该句型,可以在 statement1 ~ statementN 之间选其中一个执行。

示例语法:

// if ...

if (表达式) 语句;

if (表达式)

  语句;

if (表达式) {

  代码块;

}

 

// if ... else

if (表达式) 语句;else 语句;

if (表达式)

  语句;else 

  语句;

if (表达式) {

  代码块;

} else {

  代码块;

}

// if ... else if ... else ...

if (表达式) {

  代码块;

} else if (表达式) {

  代码块;

} else if (表达式) {

  代码块;

} else {

  代码块;

}

 

switch 语句

示例语法:

switch (表达式) {

  case 变量:

    语句;

  case 数字:

    语句;

    break;

  case 字符串:

    语句;

  default:

    语句;

}

· default 分支可以省略不写。

· case 关键词后面只能使用:变量数字字符串

示例代码:

var exp = 10;

switch ( exp ) {case "10":

  console.log("string 10");

  break;case 10:

  console.log("number 10");

  break;case exp:

  console.log("var exp");

  break;default:

  console.log("default");

}

输出:

number 10

 

for 语句

示例语法:

for (语句; 语句; 语句)

  语句;

for (语句; 语句; 语句) {

  代码块;

}

· 支持使用 breakcontinue 关键词。

示例代码:

for (var i = 0; i < 3; ++i) {

  console.log(i);

  if( i >= 1) break;

}

输出:

01

 

while 语句

示例语法:

while (表达式)

  语句;

while (表达式){

  代码块;

}

do {

  代码块;

} while (表达式)

· 表达式 true 时,循环执行语句代码块

· 支持使用 breakcontinue 关键词。

 

5.require函数

.wxs模块中引用其他 wxs 文件模块,可以使用 require 函数。

引用的时候,要注意如下几点:

· 只能引用 .wxs 文件模块,且必须使用相对路径。

· wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。

· 如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行。

示例代码:

// /pages/tools.wxs

var foo = "'hello world' from tools.wxs";var bar = function (d) {

  return d;

}module.exports = {

  FOO: foo,

  bar: bar,

};module.exports.msg = "some msg";

// /pages/logic.wxs

var tools = require("./tools.wxs");

console.log(tools.FOO);console.log(tools.bar("logic.wxs"));console.log(tools.msg);

<!-- /page/index/index.wxml -->

<wxs src="./../logic.wxs" module="logic" />

 

3.WXSS

WXSS(WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。

WXSS 用来决定 WXML 的组件应该怎么显示。

为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。

CSS 相比,WXSS 扩展的特性有:

· 尺寸单位  样式导入

尺寸单位

· rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

· 

设备

rpx换算px (屏幕宽度/750)

px换算rpx (750/屏幕宽度)

iPhone5

1rpx = 0.42px

1px = 2.34rpx

iPhone6

1rpx = 0.5px

1px = 2rpx

iPhone6 Plus

1rpx = 0.552px

1px = 1.81rpx

 

建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。

注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

 

样式导入

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。

示例代码:

/** common.wxss **/.small-p {

  padding:5px;

}

/** app.wxss **/@import "common.wxss";.middle-p {

  padding:15px;

}

 

内联样式

框架组件上支持使用 style、class 属性来控制组件的样式。

· style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。

<view style="color:{{color}};" />

· class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。

<view class="normal_view" />

 

选择器

目前支持的选择器有:

选择器

样例

样例描述

.class

.intro

选择所有拥有 class="intro" 的组件

#id

#firstname

选择拥有 id="firstname" 的组件

element

view

选择所有 view 组件

element, element

view, checkbox

选择所有文档的 view 组件和所有的 checkbox 组件

::after

view::after

在 view 组件后边插入内容

::before

view::before

在 view 组件前边插入内容

全局样式与局部样式

定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。

 

猜你喜欢

转载自blog.csdn.net/qq_38266792/article/details/80525384