微信小程序基础

简介

它是什么

  • 一套用来开发在微信中运行的手机app框架

组成结构

  • 视图层wxml、样式文件wxss、逻辑层js
  • 数据的双向绑定

用户在视图上的修改会自动同步到数据模型中去,一样若是数据模型中的数据发生改变,也会同步到视图层中。css

获取AppID

  • 网址:https://mp.weixin.qq.com/
  • 注册登陆后,在 设置->开发设置->开发者ID 中,可找到AppID(在 微信开发者工具 新建小程序项目时须要)

获取微信开发者工具

微信开发者工具

  • 左上角模拟器 编辑器 调试器控制编辑器视图,iphone6 100% WIFI分别为机型选择、缩放比例、网络选择
  • 编辑区域上面的编译模式中,普通编辑模式下,每次刷新都是从新载入index刷新,能够经过添加编译模式,自定义刷新指定页面,这样方便调试
  • 预览 能够在手机上预览小程序
  • 远程调试 手机能够访问小程序,同时编辑器提供控制台一系列工具用于调试

入门

一套页面文件

index.js index.json index.wxss index.wxmlhtml

程序配置

即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

  • window配置项中有一项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)
    }
})

生命周期

App生命周期

onLaunch onLaunch在小程序运行期间,只会运行一次;程序销毁(过了一段时间没有运行,或手动删除了小程序,再次添加运行)以后,再次启动就会执行
onShow 每次在后台切换过来,就会执行
onHide 每次切换到后台,就会执行缓存

页面生命周期

onLoad 页面加载的时候执行,只会执行一次
onReady 页面第一次渲染完成以后,只会执行一次
onShow 页面显示的时候就会执行,能够执行屡次
onHide 页面隐藏就会执行,能够执行屡次
onUnload 页面卸载的时候执行,只会执行一次
进入小程序首页,会依次执行onLoad onShow onReady,经过tabBar首页切换到视频页,index不会被卸载,因此不会执行onUnload,可是会执行onHide,进入视频页,视频页会执行视频页的onLoad、onShow、onReady,而后再经过tabBar从视频页切换回首页,视频页执行onHide,首页执行onShow微信

  • tab之间的切换,不会让页面从新加载,也就不会卸载,只会隐藏起来

在首页中加入导航navigator,经过navigator的方式跳转到视频页,首页仍是会执行隐藏方法onHide,视频页左上角出现返回的返回方式,用这种返回方式返回到首页,视频页会发生销毁执行onUnload

  • 在进行NavigatorTo,跳转到的那个目标页面会进行加载(load),跳转以前的页面会被隐藏(hide)
  • 回退(NavigatorBack),目标页面会show(不是加载),回退以前的页面会被卸载(unload)

页面渲染

循环渲染

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并非真正的元素,用来辅助渲染一些平级的元素

<block wx:if="{{score===80}}">
    <view>{{name}}</view>
    <view>{{score}}</view>
    <view>等级A</view>
</block>
<block wx:else>学生不符合要求</block>

使用template

//定义好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的内容不少,能够将模板里的内容单独出来一个文件(template.wxml),放置的位置视状况而定;
  • 页面中引入模板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)
}

clipboard.png

<view bind:tap="onTap" id='view' data-name="容器">
    <text id="text" data-name="文字">点按我能够打印信息</text>
</view>
onTap(e){
    console.log(e)
}

点击view空白部分:
clipboard.png

点击text文字:
clipboard.png

bindtap 不阻止事件冒泡
catchtap 阻止事件冒泡

<view catch:tap="onTap" id='view' data-name="容器">
    <text id="text" data-name="文字">点按我能够打印信息</text>
</view>

wxss

rpx

rpx规定屏幕宽为750px
clipboard.png

支持的选择器

.class #id element element, element :after :before
(好比不支持css3的属性选择器)

wxss引入其余wxss文件

clipboard.png

style和data

<text style='color: {{color}}'>点按我能够打印信息</text>
data: {
    color: 'red'
}

wxs辅助渲染

<!--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"
}

clipboard.png

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

setData更新数据与页面

<view>{{magicNumber}}</view>
<button bindtap='onTap'>点击</button>
data: {
    magicNumber: Math.random()
},
onTap(){
    //this.data.magicNumber = 8999 //这种更新方式是没用的
    this.setData({
      magicNumber: Math.random() //相似react更新方式
    })
}

clipboard.png
data变化,视图不必定更新,这是一个异步的过程。

组件

小程序内置组件

<input type="text" value="hello" bindinput='onInputChange'></input>
onInputChange(e){
    console.log(e)
    //return Math.random()
    //还能够return出去一个值,控制输入框东西的显示
}

在输入框输入的时候,控制台不断打印事件对象,e.detail.value即为输入框内容

自定义组件

自定义组件,能够单独出来:
clipboard.png

  • 组件js中使用Component注册组件
  • Component注册的是组件,Page注册的是页面

clipboard.png
clipboard.png
而后在页面的json文件中注册自定义组件:
clipboard.png
在页面中使用自定义组件:

<!--index.wxml-->
<magic-number></magic-number>

其中,在magicNumber.wxml中

<text>magicNumber自定义组件</text>

因此在index页面中显示的就是文字“magicNumber自定义组件”。

  • 自定义组件定义事件要写在methods中:
<!-- 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中显示的自定义组件文字,控制台打印处相关信息:
clipboard.png

点击文字页面取整显示:

<!-- 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}}与自定义组件中的随机数一致,在自定义组件的生命周期函数中:
clipboard.png

自定义组件的自定义属性要小写,并用烤串形式:

<!-- 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

具体参数可在官网查阅 关于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方式,顶部会出现回退的样式:
clipboard.png

<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页
clipboard.png
clipboard.png
clipboard.png
clipboard.png

<!--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页,当前小程序加载的惟一页面,顶部没有返回按钮
clipboard.png
clipboard.png
clipboard.png

使用API进行导航

navigate wx.navigateTo(OBJECT) 跳转到
redirect wx.redirectTo(OBJECT) 重定向
switchTab wx.switchTab(OBJECT) 跳转到某个tab
navigateBack 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页

受权相关API

受权方式:
用户信息 (受权button)
其余信息受权 (wx.authorize(OBJECT)先进行受权直接获取信息,未受权会先进行受权)

<!--index.wxml-->
<!-- 点击出现用户受权弹框,点击取消或者肯定会执行回调函数 -->
<!-- onGetUserInfo即为执行的回调 -->
<button open-type='getUserInfo' bindgetuserinfo='onGetUserInfo'>获取用户信息</button>
// index.js
Page({
  onGetUserInfo(e){ //接收一个事件对象,将其打印出来
    console.log(e)
  }
})

点击按钮,用户出现受权弹窗:(以前进行过受权操做可先清除受权数据)
clipboard.png
clipboard.png
clipboard.png
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的回调:
clipboard.png
以点击容许为例,控制台打印为:
clipboard.png

<!--index.wxml-->
<button bindtap='onGetLocation'>获取位置</button> 
// index.js
Page({
  onGetLocation(){
    wx.getLocation({ //获取到受权后的信息
      success: msg=>console.log(msg, "位置"),
      fail: e=>console.log(e, "没获取到位置")
    })
  }
})

点击按钮:
clipboard.png
选择肯定,控制台就会打印出地理信息相关信息:
clipboard.png

<!--index.wxml-->
<button bindtap='onGetSetting'>获取受权信息</button> 
// index.js
Page({
  onGetSetting(){
    wx.getSetting({ //微信提供这样一个API用于告诉哪些信息受权了哪些信息没有受权
      success: msg => console.log(msg, "受权相关信息"),
    })
  }
})

clipboard.png
clipboard.png
clipboard.png
clipboard.png
clipboard.png

<!--index.wxml-->
<button bindtap='onGotoSetting'>打开受权信息面板</button> 
// index.js
Page({
  onGotoSetting(){
    wx.openSetting({
      success: msg=>console.log(msg, "设置完成")
    })
  }
})

点击能够进入受权面板:
clipboard.png

使用缓存

微信里能够同步或者异步地缓存数据

<!--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)
          }
        })
      }
    })
  }
})

点击按钮,便可实现缓存:
clipboard.png
同时能够取到缓存中name为key的缓存数据,在控制台打印出来:
clipboard.png
以上设置缓存的方式是异步的。
如下为同步设置缓存的方式:

<!--index.wxml-->
<button bindtap='onCache'>缓存数据</button>
// index.js
Page({
  onCache(){
    wx.setStorageSync('names', 'Hurley')
    let ns = wx.getStorageInfoSync('names')
    console.log(ns)
  }
})

点击按钮,缓存中写入names:
clipboard.png
并在控制台打印出:
clipboard.png

<!--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)
      }
    })
  }
})

点击按钮,控制台出现报错:
clipboard.png
所以,在小程序里进行请求须要进行相应配置:
clipboard.png
这样就能够经过接口请求到数据,快速调试时设置不校验域名,能够请求到数据

请求过程当中的反馈

clipboard.png
clipboard.png

相关文章
相关标签/搜索