zoukankan      html  css  js  c++  java
  • 小程序开发备忘

    相关资料

    小程序简易教程
    框架介绍
    组件介绍
    Api

    PART1 构成

    小程序包含一个描述整体程序的 app 和多个描述各自页面的 page。
    一个小程序主体部分由三个文件组成,必须放在项目的根目录,如下:
    文件必需作用
    app.js小程序逻辑(配置第一次打开时, 崩溃,后台切换时需要做的逻辑处理)
    app.json小程序公共配置 (小程序有哪些页面page, 窗口的背景/颜色, 超时设置等)
    app.wxss小程序公共样式表
    具体每个页面page是由由四个文件组成,分别是:
    文件类型必需作用
    js页面逻辑
    wxml页面结构
    json页面配置
    wxss页面样式表

    比如整个小程序所有的page的路径信息需要配置到app.json中,举例如下:
    {
      "pages": [ 
        "pages/login/login",
        "pages/index/index",
        "pages/order/order",
        "pages/solution/solution",
        "pages/personal/personal",
        "pages/navigation/navigation",
        "pages/solutionChart/solutionChart"
      ],
      "window": {
        "backgroundTextStyle": "light",
        "navigationBarBackgroundColor": "#fff",
        "navigationBarTitleText": "WeChat",
        "navigationBarTextStyle": "black"
      }
    }
    "pages" #用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。

    用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径+文件名 信息。文件名不需要写文件后缀,框架会自动去寻找对于位置的 .json, .js, .wxml, .wxss 四个文件进行处理。

    数组的第一项代表小程序的初始页面(首页)。小程序中新增/减少页面,都需要对 pages 数组进行修改。

    如开发目录为:

    ├── app.js #整个小程序的通用配置(配置第一次打开时, 崩溃,后台切换时需要做的逻辑处理)
    ├── app.json #小程序公共配置 (小程序有哪些页面page, 窗口的背景/颜色, 超时设置等)
    ├── app.wxss #小程序整体通用公共样式表
    ├── pages #小程序具体的各个子页面目录
    │   │── index  #一个小程序page对应以下4个文件组成
    │   │   ├── index.wxml  #相当于web的html页面
    │   │   ├── index.js #控制页面的逻辑
    │   │   ├── index.json #配置本页面的标题,背景等
    │   │   └── index.wxss #页面的个性化样式
    │   └── logs
    │       ├── logs.wxml
    │       └── logs.js
    └── utils #用户自定义用于存放工具类
    
    └── images #用户自定义存放图片路径


    则需要在 app.json 中写

    {
      "pages":[
        "pages/index/index",//这里对应的就是pages/index/index.wxml页面
        "pages/logs/logs"
      ]
    }

    "window" #定义小程序所有页面的顶部背景颜色,文字颜色定义等

    PART2 逻辑层和视图层

    以数据绑定的程序为例
    index目录就是一个具体的页面, 下面有js,wxml,wxss等文件用来描述index.wxml这个页面
    app.json中的pages配置了index这个页面
    {
      "pages":[
        "index/index"
      ],
      "window":{
        "backgroundTextStyle":"light",
        "navigationBarBackgroundColor": "#fff",
        "navigationBarTitleText": "WeChat",
        "navigationBarTextStyle":"black"
      }
    }
    
    打开index.wxml页面
    <!--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>

    其中<view> 和<button>等分别是小程序提供的视图组件和表单组件, 可以理解为html中的标签
    可直接使用并配置相关参数(事件,大小等属性), 并由小程序渲染.

    index.js 代码如下
    // pages/index/index.js
    Page({
    
    /**
    * 页面的初始数据
    */
    data: {
    array: ['当天', '本月', '近三月','近半年','本年'],
    index: 0,
    date: '2016-09-01',
    time: '12:01',
    barItem: [
    {
    name: '利润汇总',
    image: '../../images/menu1_unfocus.png',
    selectedImage: '../../images/menu1_focus.png',
    selected: false,
    color: '#666666',
    url: '/pages/solution/solution'
    },
    {
    name: '每日营业情况',
    image: '../../images/menu3_unfocus.png',
    selectedImage: '../../images/menu3_focus.png',
    selected: true,
    color:'#FF0000',
    url: '/pages/index/index'
    },
    {
    name: '运营支出',
    image: '../../images/menu2_unfocus.png',
    selectedImage: '../../images/menu2_focus.png',
    selected: false,
    color: '#666666',
    url: '/pages/order/order'
    },
    // {
    // name: '',
    // image: '../../images/menu4_unfocus.png',
    // selectedImage: '../../images/menu4_focus.png',
    // selected: false,
    // url: '/pages/personal/personal'
    // },
    ],
    successresponseData: [],
    datalist:[]
    },
    
    //更新日期选型,刷新取值
    bindPickerChange: function (e) {
    
    var that = this;
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
    index: e.detail.value
    })
    wx.request({
    url: require('../../config').getnumUrl,
    //url: 'http://localhost:8081/framework-protal/main/gas/getsale',
    method: 'POST',
    header: {
    'content-type': 'application/x-www-form-urlencoded'
    },
    
    data: {
    gasid: wx.getStorageSync('gasid'),
    type: e.detail.value
    },
    success: function (res) {
    console.log('success')
    console.log(res.data)
    that.setData({
    numresponseData: res.data.response,
    })
    },
    fail: function (res) {
    console.log('fail')
    }
    
    })
    wx.request({
    url: require('../../config').getsaleUrl,
    //url: 'http://localhost:8081/framework-protal/main/gas/getsale',
    method: 'POST',
    header: {
    'content-type': 'application/x-www-form-urlencoded'
    },
    data: { gasid: wx.getStorageSync('gasid') },
    success: function (res) {
    console.log('success')
    console.log(res.data)
    that.setData({
    responseData: res.data.response,
    })
    var gasnameArr = wx.getStorageSync('gasname');
    var gasname;
    if (gasnameArr.length != 0 && gasnameArr != undefined) {
    gasname = gasnameArr.join(",");
    if (gasname.length > 10) {
    gasname = gasname.substring(0, 10) + "...";
    }
    }
    that.setData({
    gasname: gasname,
    gasnameArr: wx.getStorageSync('gasname'),
    })
    },
    fail: function (res) {
    console.log('fail')
    }
    
    })
    
    
    
    
    },
    /**
    * 生命周期函数--监听页面加载
    */
    onLoad: function (options) {
    let that =this;
    var gasnameArr = wx.getStorageSync('gasname');
    var gasname;
    if (gasnameArr.length != 0 && gasnameArr != undefined) {
    gasname = gasnameArr.join(",");
    if (gasname.length > 10) {
    gasname = gasname.substring(0, 10) + "...";
    }
    }
    that.setData({
    gasname: gasname,
    gasnameArr: wx.getStorageSync('gasname')
    })
    /*wx.request({
    url: require('../../config').getsaleUrl,
    //url: 'http://localhost:8081/framework-protal/main/gas/getsale',
    method: 'POST',
    header: {
    'content-type': 'application/x-www-form-urlencoded'
    },
    
    data: { gasid: wx.getStorageSync('gasid') },
    success: function (res) {
    console.log('success')
    console.log(res.data)
    that.setData({
    responseData: res.data.response,
    })
    },
    fail: function (res) {
    console.log('fail')
    }
    
    }) */
    
    
    
    wx.request({
    url: require('../../config').getnumUrl,
    //url: 'http://localhost:8081/framework-protal/main/gas/getsale',
    method: 'POST',
    header: {
    'content-type': 'application/x-www-form-urlencoded'
    },
    
    data: {
    gasid: wx.getStorageSync('gasid'),
    type:0 //默认值为当天
    },
    success: function (res) {
    console.log('success')
    console.log(res.data)
    that.setData({
    numresponseData: res.data.response,
    })
    },
    fail: function (res) {
    console.log('fail')
    }
    
    })
    
    
    },
    //加油站点击事件
    bindButtonTap: function (e) {
    wx.redirectTo({
    url: '/pages/personal/personal?userid=' + wx.getStorageSync('userid') + '&type=1',
    })
    },
    /**
    * 生命周期函数--监听页面初次渲染完成
    */
    onReady: function () {
    },
    
    /**
    * 生命周期函数--监听页面显示
    */
    onShow: function () {
    },
    
    /**
    * 生命周期函数--监听页面隐藏
    */
    onHide: function () {
    },
    
    /**
    * 生命周期函数--监听页面卸载
    */
    onUnload: function () {
    },
    
    /**
    * 页面相关事件处理函数--监听用户下拉动作
    */
    onPullDownRefresh: function () {
    },
    
    /**
    * 页面上拉触底事件的处理函数
    */
    onReachBottom: function () {
    },
    
    /**
    * 用户点击右上角分享
    */
    onShareAppMessage: function () {
    },
    
    /**
    * 菜单单击
    */
    onBarItemClick: function (e) {
    let url = this.data.barItem[e.currentTarget.dataset.sno].url;
    if (url == null || url == '') {
    return;
    }
    wx.redirectTo({
    url: url
    })
    },
    /**
    * 导航栏单击
    */
    onNavigation: function () {
    wx.navigateTo({
    url: '/pages/navigation/navigation'
    })
    },
    
    onHotPro2: function(e) {
    wx.navigateTo({
    url: '/pages/groupLine/groupLine?id=' + e.currentTarget.id,
    })
    },
    
    onHotPro3: function(e) {
    
    
    wx.login({ //调用微信登录接口
    success: function (res) {
    wx.setStorageSync("code", res.code)
    let code = wx.getStorageSync("code")
    //
    wx.request({
    url: 'http://172.16.16.145:8180/wxService/wx/queryProductDetail',
    method: 'GET',
    
    data: {
    id: 3,
    },
    success: function (res) {
    console.log('success')
    console.log(res)
    },
    fail: function (res) {
    console.log('fail')
    }
    });
    },
    fail: function () {
    
    }
    });
    
    
    
    
    
    wx.navigateTo({
    url: '/pages/flowPay/flowPay',
    })
    },
    
    onCase1: function(e) {
    
    wx.navigateTo({
    url: '/pages/case/case?id=' + e.currentTarget.id,
    })
    },
    //输入搜索内容
    searchmessage: function (e) {
    this.setData({
    searchmessage: e.detail.value
    })
    },
    //点击搜索
    onsearch: function (e) {
    
    wx.navigateTo({
    url: '/pages/order/order?productName=' + this.data.searchmessage,
    })
    },
    //点击注册
    regist: function (e) {
    wx.navigateTo({
    url: '/pages/login/reg/reg',
    })
    }
    })
    index.js中的data属性用于配置页面第一次渲染使用的初始数据.
    页面加载时,data 将会以JSON字符串的形式由逻辑层传至渲染层,因此data中的数据必须是可以转成JSON的类型:字符串,数字,布尔值,对象,数组。
    举例代码中data定义了text 和array
    Page({
      data: {
        text: 'init data',
        array: [{msg: '1'}, {msg: '2'}]
      }
    })
    对应index.wxml中的
    <view>{{text}}</view>
    <view>{{array[0].msg}}</view>
    页面初始化的时候小程序会自动从js的data中加载对应的text和array数据初始化显示到{{}}中.
    <view>{{text}}</view>
    <button bindtap="changeText"> Change normal data </button>
    wxml中在按钮上配置的changeText定了点击对应的函数,在js中对应changeText()方法中:
      changeText: function () {
        // this.data.text = 'changed data'  // bad, it can not work
        console.log(this.data.text);
        var text2="hola baby";
        this.setData({
          text: text2,
        })
        console.log(this.data.text);
      }
    可以通过this.setData来修改text的值.在changeText中通过 this.data.text可以获取到初始化设置的data中的属性的text的值
    Page({
      data: {
        text: 'init data',
        array: [{msg: '1'}, {msg: '2'}]
      }
    })
    以本例
    第一次打印的是index.js中data中设置的text初始化的值(this.data.text) 为 init data
    通过this.setData()方法中修改text后, 重新打印this.data.text的值即变为了我们设置的hola baby
    通过this.setData()修改text成功后, 对应页面上的值也会自动改变.

    this.setData解释:

    Page.prototype.setData(Object data, Function callback)

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


    以上可见对应的视图层控制在wxml中 逻辑控制在js中

    引用官方的说明如下: 视图层(由wxml, wxss,wxs等来支持实现): 

    https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/

    WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。

    它支持数据绑定, 列表渲染,条件渲染,模版 事件, 引用等.

    引用官方的说明如下: 逻辑层(由页面的js, 小程序api等来支持实现): 

    https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/

    其中小程序提供的api说明如下:

    小程序开发框架提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。

    小程序原生API类型如下:
    • 事件监听 (我们约定,以 on 开头的 API 用来监听某个事件是否触发,如:wx.onSocketOpen 监听 WebSocket 连接打开事件,wx.onCompassChange 等。)
    • 同步API (如 wx.setStorage 数据存储:将数据存储在本地缓存中指定的 key 中。数据存储生命周期跟小程序本身一致)
    • 异步API (如wx.setStorageSync 异步的数据存储, 如wx.request 发起异步网络请求)

    以上我们可以通过api进行小程序全局的本地数据存储和获取, 或者发起http请求
    比如在小程序页面打开的时候加载后台数据:
    在页面index.js的
    onLoad: function (options) {}监听页面加载自动调用的onload方法中
    通过wx:request请求后台数据

    var that = this;
    wx.request({ //请求后台数据
        url: require('../../config').getregistcostlistUrl,
        method: 'POST',
        header: {
            'content-type': 'application/x-www-form-urlencoded'
        },
        data: { //向后台数据发送的请求参数
            id: wx.getStorageSync('gasid'), //以id为name,value为全局缓存中key为gasid的值, 发送给后台
            type:3
        },
        success: function (res) { //请求成功后的回调方法
            that.setData({
               responseData: res.data  //将请求成功的值,通过this.setData 修改保存到responseData中, 这里的responseData对应可以下wxml中{{responseData}}来同步显示.甚至如果responseData是对象,我们可以新增属性responseData.name responseData.pwd而不需要预先定义.
          })
        let a = 0;
            for (let i = 0; i < res.data.length; i++) {
            a = a + res.data[i].total
        }
        that.setData({
            total: a
        })
        },
        fail: function (res) {
        console.log('fail')
        }
     })


    以功能多选为例

    <block wx:for="{{responseData}}" wx:key="{{responseData}}">
     <view class='content' id='{{item.id}}' data-text="{{item.name}}" name='{{item.name}}' bindtap='itemSelected'>
      <text>{{item.name}}</text> 
      <image id='img-{{item.id}}' class='select_icon' src="{{item.isSelected?'../../images/selected.png':''}}"></image>
     {{iconVar}}
     </view>
    </block>
    responseData为数据集合被循环.
    item为循环变量, item.name为加油站的名字, view中的data-text后台函数就可以通过
     var name = e.currentTarget.dataset.text; 来获取值. 这是小程序约定的数据传递绑定方式.
    //选中
      itemSelected: function (e) {
        var id = e.currentTarget.id;//e.currentTarget.dataset.index;//当前选中加油站的id
        var name = e.currentTarget.dataset.text;
        var replyLikeArr = this.data.replyLike;
        var replyLikeNameArr = this.data.replyLikeName;
        //初次加载的加油站对象数据通过onload方法中的this.setData保存在responseData中
        //而wxml中有{{responseData}}, 所以我们可以通过this.data.responseData获取
        
        for (var i = 0; i < this.data.responseData.length; i++) {
          if (this.data.responseData[i].id==id){
            var item = this.data.responseData[i];//遍历加油站集合,将结合中与将当前选中的加油站id相同的那个对象获取到
            if(!item.isSelected){ //加油站一开始并没有isSelected属性,这里第一次肯定是false.本段代码执行后,加油站对象就多了一个isSelect属性,默认值为false
              if (replyLikeArr.length > 2) {
                wx.showToast({
                  title: '选择不可超过3个',
                  icon: 'loading',
                  duration: 2000
                })
                return;
              }
            }
            item.isSelected = !item.isSelected; //将加油站选中的标记属性isSelect置为相反
            if (item.isSelected){ //如果加油站被选中的属性为是,这将其id和名字放入新的集合变量中
                replyLikeArr.push(id);
                replyLikeNameArr.push(item.name);
            }else{//如果加油站被选中的属性为否,这将其id和名字从选中集合变量中删除
              replyLikeArr.splice(replyLikeArr.indexOf(id),1);
              replyLikeNameArr.splice(replyLikeNameArr.indexOf(item.name),1);
            }
           break;
          }
        }
        this.setData({
            //务必通过setData修改以上操作.否则新增isSelect属性或者修改isSelect属性的值都不会发生变化
          responseData: this.data.responseData,
          replyLike: replyLikeArr,
          replyLikeName: replyLikeNameArr
        });
      },
    变量replyLikeArr和replyLikeNameArr被定义在page:data中从来存放被选中的加油站的id和名字.

    通过wxml中的
    <image id='img-{{item.id}}' class='select_icon' src="{{item.isSelected?'../../images/selected.png':''}}"></image>
    可见,如果加油站一开始没有isSelect属性或者属性为false就不会出现选中的图片.

    这里展示了如何循环遍历, 如果在方法中获取页面上的传值, 如何在方法中获取页面的数据并修改,并且显示了如果通过修改页面的值同同时控制页面效果.这个效果是基于小程序页面数据绑定单向的这一特性(修改页面的属性,这页面上的值也会自动变化).
    另外如需跨页面传值可通过跳转时url绑定或者api的wx.setStorage(key,object) 来实现. 特别是wx.setStorage和wx.getStorage可实现整个小程序内部的本地缓存数据的存放和读取.

    同样图标选中变红的效果

    <view class="layout_horizontal" style='float:left; 80%;'>
      <block wx:for="{{responseData}}" 
        wx:key="{{responseData}}" 
        wx:for-item="item" wx:for-index="index">
        <view  bindtap="chooseGood" 
           style='display:inline-block; 23%; margin-left:2%;' 
             data-index="{{index}}" data-goodId="{{item.goodid}}">
         <button class="{{index==idx?'btnRed':'btn1'}}" >{{item.goodname}}</button>
        </view>
    </block>
    </view>
    点击后调用了chooseGood方法
    到对应页面的js中将查看方法
     //选择产品类型,同时更新数据更新报表
      chooseGood: function (e) {
        let index = e.currentTarget.dataset.index;
        var goodid = e.currentTarget.dataset.goodid;//所选产品类型的id
        this.setData({
          idx: index
        })
        wx.setStorageSync("chooseGoodid", goodid);
        this.getXYData();
      },
    页面上有data-goodId="{{item.goodid}} 和 data-index="{{index}}" 其中index是循环的索引(从0开始)
    所以我们可以通过e.currentTarget.dataset.index和e.currentTarget.dataset.goodid来获取值
    我们在页面上定义如果index为idx则样式为btnRed(被选中) 否则为btn1样式(没被选中)
    <button class="{{index==idx?'btnRed':'btn1'}}" >{{item.goodname}}</button>
    此时只需要在js中将idx的值改为当前索引值即可. 此时被选中的商品的索引传给了idx,页面上
    它的索引值就和idx一致,它就会使用btnRed的样式,表示为被选中.

    而效果
    点击显示隐藏的其他数据并将整体其他view下移可通过计算
    一开始获取商品类型如果超过4个,则数组另存为responseData 并截取只保留4个显示.
    点击按钮更多时,判断本地缓存中wx.getStorageSync('goodsType')商品类型数量,
    如果超过4个则修改样式
    size = responseData.length / 4;
    size = size * 60;
    对应wxml中
    <view style='font-size:20rpx ;100% ;display: flex;margin-left:3%;margin-top:{{moveSize}}rpx'>
    moveSize变量初始在page.data设为0,此时即可通过上外距撑开.
    反之,再次点击图标,则会收缩.隐藏商品类型,只显示4个.
    此时将本地缓存中商品类型截取, 保留4个并复制给页面上的需要遍历的变量.
    并将需要下拉的外边距变量moveSize的值改为0即可.
    这些操作后都需要this.setData来保存.
      moreGoods: function () {
        var objArrAll = wx.getStorageSync('goodsType');
        var responseData=this.data.responseData;
        var size = 0;
        var ifMore = this.data.ifMore; //一开始没有这多个属性的话此时会新增属性,默认值为false
        //商品类型超过4个才有展开的需求
        if (objArrAll.length>4){
          if (ifMore){//已展开,则菜单进行收缩操作
           //size默认已值为0
            responseData = responseData.slice(0,4);
            ifMore=false;//标记为未展开
          }else{ //未展开, 则对菜单进行展开操作
            responseData = objArrAll; //将全部商品赋给需要显示的遍历的对象
            ifMore = true;//标记展开
            //修改样式
            size = responseData.length / 4;
            size = size * 60;
          }
        }
    
        this.setData({
          responseData,
          moveSize: size,
          ifMore,
        })
      },







  • 相关阅读:
    JDK源码分析之hashmap就这么简单理解
    JVM笔记11-类加载器和OSGI
    JVM笔记10-性能优化之高级特性
    Java并发编程笔记之ThreadLocal内存泄漏探究
    Java并发编程笔记之FutureTask源码分析
    Java并发编程笔记之SimpleDateFormat源码分析
    Java并发编程笔记之Timer源码分析
    Java并发编程笔记之Semaphore信号量源码分析
    Java并发编程笔记之CyclicBarrier源码分析
    Java并发编程笔记之 CountDownLatch闭锁的源码分析
  • 原文地址:https://www.cnblogs.com/redcoatjk/p/10043240.html
Copyright © 2011-2022 走看看