精华内容
下载资源
问答
  • 微信小程序开发框架搭建

    万次阅读 2016-11-30 10:45:24
    使用开发工具的正确姿势微信提供的开发工具的编辑功能不是一般的水,写代码肯定不能用它,否则就是浪费生命.不说别的,连自动保存都没有,第一次写时写了一个多小时,后面下班直接关掉,也不弹出提示说没保存.然后第二天...

    使用开发工具的正确姿势

    微信提供的开发工具的编辑功能不是一般的水,写代码肯定不能用它,否则就是浪费生命.不说别的,连自动保存都没有,第一次写时写了一个多小时,后面下班直接关掉,也不弹出提示说没保存.然后第二天过来,写的代码全没了!!! 顿时感到巨坑无比.这些工具开发人员吃干饭的么???
    (后来的版本已经修复不能自动保存的问题了,当然编辑功能还是不好用.)

    它的正确用法是作为运行和调试工具.

    那么适合作为编辑工具的是: webStorm.基于IntelJ内核,开启Dracula主题,跟Android studio的使用习惯非常接近,so cool!各种方法提示,自动保存,快速查找…应有尽有.闭源的微信开发工具就不要用来写代码了,珍惜生命.
    webStorm要识别wxml和wxss,还需要配置一下文件类型:(看下面别人截的图)
    记住html和css里都要加上微信小程序对应的类型

    1478137328137_4.png

    综上,开发时,用webstorm来写代码,用微信开发工具来运行和调试,速度飕飕的!

    网络请求的封装

    微信提供了底层网络驱动以及成功和失败的回调.但对于一个项目中的实际使用而言,仍然还是显得繁琐,还有很多封装和简化的空间.

    wx.request({
      url: 'test.php',//请求的url
      data: {//请求的参数
         x: '' ,
         y: ''
      },
      header: {//请求头
          'Content-Type': 'application/json'
      },
      method:"POST",
      success: function(res) {//成功的回调
        console.log(res.data)
      }
    })
    

    网络框架二次封装的一般姿势

    对于一个网络访问来说,请求一般是get和post,拼上各种参数以及请求头,然后拿到回来的响应,解析并得到最终需要的数据.

    对于具体项目来说,请求时会有每个(或大多数)请求都要带的参数,都要带的请求头,返回的数据格式可能都是一致的,那么基于此,对微信的网络请求api进行二次封装:

    在我目前的项目中,

    请求:

    大多数请求是post,基本上每个请求都需要携带sessionId来与服务器验证登录状态,还有很多请求是基于分页的,需要带上pageSize和pageIndex.
    再跟页面逻辑关联起来,请求可能是因为第一次进入页面,或者刷新,或者上拉加载更多.

    响应:

    大多数拿到的数据格式是标准json格式,如下

    {
        "code":1,
        "data":xxx,//可能是String,也可能是JsonObject,或JsonArray,也可能是null,或undefined
        "msg":yyy//可能为空
    
    }
    

    通过请求的状态码code来判断这个请求是否真正成功.我们的项目中还有常见的是code=5:登录过期或未登录,code=2: 没有找到对应的内容 等等.

    我们实际使用中需要的:

    如果是大多数情况的请求时,只需要指定:

    1. url的尾部
    2. 该请求的非一般的参数
    3. 该请求由什么动作引起的(第一次进入,刷新,加载更多)

    对于响应,我们只需要:

    1. 成功时:拿到data里面的数据
    2. 失败时,拿到失败的信息(细分一下,包括可以直接显示给用户的和不能让用户看到的),以及失败状态码
    3. 数据为空的回调:(常见于列表数据的加载)

    我们期望的api是:

    netUtil.buildRequest(page,urlTail,params,callback)//必须的参数和回调
    .setXxx(xxx)//额外的设置,链式调用
    ..
    .send();//最终发出请求的动作
    

    基于上面的分析,封装如下:

    定义好携带构建请求的对象:

    //这两个错误码是项目接口文档统一定义好的
    const code_unlogin = 5;
    const code_unfound = 2;
    
    function requestConfig(){
        this.page;  //页面对象
        this.isNewApi = true;
        this.urlTail='';
        this.params={
            pageIndex:0,
            pageSize:getApp().globalData.defaultPageSize,
            session_id:getApp().globalData.session_id
        };
        this.netMethod='POST';
        this.callback={
            onPre: function(){},
            onEnd: function(){
    
            },
            onSuccess:function (data){},
            onEmpty : function(){},
            onError : function(msgCanShow,code,hiddenMsg){},
            onUnlogin: function(){
                this.onError("您还没有登录或登录已过期,请登录",5,'')
            },
            onUnFound: function(){
                this.onError("您要的内容没有找到",2,'')
            }
        };
    
        this.setMethodGet = function(){
            this.netMethod = 'GET';
            return this;
        }
    
        this.setApiOld = function(){
            this.isNewApi = false;
            return this;
        }
    
        this.send = function(){
            request(this);
        }
    }
    

    请求的封装

    供我们调用的顶层api:

    //todo 拷贝这段代码去用--buildRequest里的callback
    /*
     onPre: function(){},
     onEnd: function(){
           hideLoadingDialog(page);
     },
     onSuccess:function (data){},
     onEmpty : function(){},
     onError : function(msgCanShow,code,hiddenMsg){},
     onUnlogin: function(){
     this.onError("您还没有登录或登录已过期,请登录",5,'')
     },
     onUnFound: function(){
     this.onError("您要的内容没有找到",2,'')
     }
    
    * */
    
    
    
    /**
     * 注意,此方法调用后还要调用.send()才是发送出去.
     * @param page
     * @param urlTail
     * @param params
     * @param callback  拷贝上方注释区的代码使用
     * @returns {requestConfig}
     */
    function buildRequest(page,urlTail,params,callback){
        var config = new requestConfig();
        config.page = page;
        config.urlTail = urlTail;
    
        if (getApp().globalData.session_id == null  || getApp().globalData.session_id == ''){
            params.session_id=''
        }else {
            params.session_id = getApp().globalData.session_id;
        }
        if (params.pageIndex == undefined || params.pageIndex <=0 || params.pageSize == 0){
            params.pageSize=0
        }else {
            if (params.pageSize == undefined){
                params.pageSize = getApp().globalData.defaultPageSize;
            }
        }
        log(params)
        config.params = params;
    
        log(config.params)
    
        //config.callback = callback;
    
        if(isFunction(callback.onPre)){
            config.callback.onPre=callback.onPre;
        }
    
        if(isFunction(callback.onEnd)){
            config.callback.onEnd=callback.onEnd;
        }
    
        if(isFunction(callback.onEmpty)){
            config.callback.onEmpty=callback.onEmpty;
        }
    
        if(isFunction(callback.onSuccess)){
            config.callback.onSuccess=callback.onSuccess;
        }
    
        if(isFunction(callback.onError)){
            config.callback.onError=callback.onError;
        }
    
        if(isFunction(callback.onUnlogin)){
            config.callback.onUnlogin=callback.onUnlogin;
        }
        if(isFunction(callback.onUnFound)){
            config.callback.onUnFound=callback.onUnFound;
        }
        return config;
    }
    

    最终请求的发送:

    function request(requestConfig){
    
        //检验三个公有参数并处理.这里与上面有所重复,是为了兼容之前写的几个api,不想改了.
        requestConfig.params.sessionId= getApp().globalData.sessionId;
        if (requestConfig.params.sessionId ==null  || requestConfig.params.sessionId == ''){
          delete  requestConfig.params.sessionId;
        }
        if (requestConfig.params.pageIndex ==0 || requestConfig.params.pageSize == 0){
           delete requestConfig.params.pageIndex ;
            delete  requestConfig.params.pageSize;
        }
    
    
        //var body = getStr("&", requestConfig.params);//拼接请求参数
        requestConfig.onPre();//请求发出前
        wx.request({
           // url: getApp().globalData.apiHeadUrl+requestConfig.urlTail+"?"+body,貌似这样写,同时不给data赋值,post请求也是可以成功的
            url: getApp().globalData.apiHeadUrl+requestConfig.urlTail,
            method:requestConfig.netMethod,
            data:requestConfig.params,
            header: {'Content-Type':'application/json'},
            success: function(res) {
                console.log(res);
                if(res.statusCode = 200){
                    var responseData = res.data
                    var code = responseData.code;
                    var msg = responseData.message;
    
                    if(code == 0){
                        var data = responseData.data;
                        var isDataNull = isOptStrNull(data);
                        if(isDataNull){
                            requestConfig.onEmpty();
                        }else{
                            requestConfig.onSuccess(data);
                        }
                    }else if(code == 2){
                        requestConfig.onUnFound();
                    }else if(code == 5){
                        requestConfig.onUnlogin();
                    }else{
                        var isMsgNull = isOptStrNull(msg);
                        if(isMsgNull){
                            var isCodeNull = isOptStrNull(code);
                            if (isCodeNull){
                                requestConfig.onError("数据异常!,请核查",code,'');
                            }else {
                                requestConfig.onError("数据异常!,错误码为"+code,code,'');
                            }
    
                        }else{
                            requestConfig.onError(msg,code,'');
                        }
                    }
                }else if(res.statusCode >= 500){
                    requestConfig.onError("服务器异常!",res.statusCode,'');
                }else if(res.statusCode >= 400 && res.statusCode < 500){
                    requestConfig.onError("没有找到内容",res.statusCode,'');
                }else{
                    requestConfig.onError("网络请求异常!",res.statusCode,'');
                }
            },
            fail:function(res){
                console.log("fail",res)
                requestConfig.onError("网络请求异常!",res.statusCode,'');
    
            },
            complete:function(res){
                // that.setData({hidden:true,toast:true});
            }
        })
    }
    

    将方法暴露,并在需要时引用:

    方法写在netUtil.js下,在该js文件最下方暴露方法:

    module.exports = {
     buildRequest:buildRequest
    
    }
    

    实际引用:

    var netUtil=require("../../utils/netUtil.js");
    

    实际使用时:

    小技巧: js无法像java一样定义好了接口,然后IDE自动生成代码.可以这样: 将callback的空方法写到netUtil的buildRequest方法上方的注释区,每次用时,点击方法名跳到那边去拷贝即可.

     var params = {};
    params.id = id;
    
    netUtil.buildRequest(that,API.Album.DETAIL,params,{
      onPre: function(){
        netUtil.showLoadingDialog(that);
      },
      onEnd:function(){
    
      },
      onSuccess:function (data){
        netUtil.showContent(that);
            ....
      },
      onEmpty : function(){
    
      },
      onError : function(msgCanShow,code,hiddenMsg){
        netUtil.showErrorPage(that,msgCanShow);
      },
      onUnlogin: function(){
        this.onError("您还没有登录或登录已过期,请登录",5,'')
      },
      onUnFound: function(){
        this.onError("您要的内容没有找到",2,'')
      }
    }).send();
    

    },

    页面状态管理

    对于大多数网络请求后显示的页面,有这么几种页面状态:

    1. 第一次进入时,网络请求过程中:显示”加载中”的状态
    2. 加载的内容为空,显示”空白页面”
    3. 加载发生错误,显示”错误页面”,此页面一般有一个点击重试的按钮.该按钮一般的逻辑是:如果没有网络则点击后去打开网络设置,如果有网络,则重新发送网络请求.
    4. 加载成功,就显示内容页.

    对于已经加载成功了,显示了内容页的”下拉拉刷新”:

    1. 页面上方会有”刷新中”的ui显示,这个微信已经原生集成,无需处理.
    2. 刷新成功,最好是弹出toast提示数据刷新成功
    3. 刷新失败,可以不提示,也可以提示,看具体选择.

    对于一些分批加载的列表数据,一般还有上拉”加载更多”的功能:

    参考微信文档中ui设计规范,上拉加载更多的ui提示应该放在页面最下部占一行,而不应该在页面中间显示一个大大的loading的效果.

    1. scrollview拉到最底部,触发加载事件,显示”加载中”的ui
    2. 加载成功,直接就将数据添加到原list上,这时也看不到最底部那行ui,所以不用处理
    3. 加载失败,则在那一行显示”加载失败”的字样,同时提示用户”上拉重试”,或者在那一行放置一个按钮,点击按钮重试.

    封装

    通过上面的分析,可以确定大部分页面的通用状态管理逻辑,那么就可以设计通用的状态管理模板了.

    ui的显示是通过Page里的data中的数据来控制的,并通过page.setData({xxx})来刷新的,原先每个页面都拷贝同样的js属性和wxml代码去实现封装,后来进行了封装,js属性用方法来封装,通过微信提供的template封装共同的wxml代码,通过import或include导入到wxml中(但是不知什么bug,template一直无法起作用).

    控制ui显示与否的属性的封装

    function netStateBean(){
    //toast的是老api,工具升级后无需设置了
        this.toastHidden=true,
        this.toastMsg='',
    
        this.loadingHidden=false,
        this.emptyHidden = true,
        this.emptyMsg='暂时没有内容,去别处逛逛吧',
    
        this.errorMsg='',
        this.errorHidden=true,
    
        this.loadmoreMsg='加载中...',
        this.loadmoreHidden=true,
    }
    

    页面js里的使用:

    Page(
        data: {
          title:'名师',//todo 设置标题栏
          emptyMsg:'暂时没有内容,去别处逛逛吧',//todo 空白页面的显示内容
          netStateBean: new netUtil.netStateBean(),
          ...
          },
          ...
        )
    

    wxml里:

    模板

        <template name="pagestate" >
            <view class ="empty_view" wx:if="{{!emptyHidden}}"   >
                <view class="center_wrapper" >
                    <view class="center_child" >
                        <icon type="info" size="45"/>
                        <view class="msg"> {{emptyMsg}}</view>
                    </view>
                </view>
            </view>
    
            <view class ="error_view" wx:if="{{!errorHidden}}"  >
                <view class="center_wrapper">
                    <view class="center_child" >
                        <icon type="warn" size="45" />
                        <view class="msg"> {{errorMsg}}</view>
                        <button  class = "retrybtn"  type="warn"  loading="{{btnLoading}}"
                                 disabled="{{btnDisabled}}" catchtap="onRetry" hover-class="other-button-hover"> 点击重试 </button>
                    </view>
                </view>
            </view>
    
         </template>
    

    使用

     <!--状态管理模板-->
    <import src="../../template/pagestate.wxml"/>
    <view >
        <template is="pagestate" data="{{...netStateBean}}"/>
    </view>
    

    js中提供API来控制页面状态:

    module.exports = {
        showContent:showContent,
        showErrorPage:showErrorPage,
        showEmptyPage:showEmptyPage,
        loadMoreNoData:loadMoreNoData,
        loadMoreStart:loadMoreStart,
        loadMoreError:loadMoreError,
        hideLoadingDialog:hideLoadingDialog,
        showLoadingDialog:showLoadingDialog,
        showSuccessToast:showSuccessToast,
        dismissToast:dismissToast,
        showFailToast:showFailToast,
        ....
    
        }
    
        //具体的实现就是,拿到page对象中的data.netStateBean,修改部分数值,然后刷新ui.
        function showEmptyPage(that){
            hideLoadingDialog(that);
            var bean = that.data.netStateBean;
            bean.emptyHidden = false;
            bean.loadingHidden = true;
            var empty = that.data.emptyMsg;
            if (isOptStrNull(empty)){//如果那个页面没有自定义空白说明文字,就使用默认的.
                empty = "没有内容,去别的页面逛逛吧"
            }
            bean.emptyMsg= empty;
            bean.contentHidden=true;//隐藏content页面
            bean.errorHidden = true;//隐藏error页面
            //刷新UI
            that.setData({
                netStateBean: bean
            });
        }
    

    最终的效果:

    black.jpg

    1478250101201_4.png

    常用页面模板的封装

    整个页面就是只有一个简单的listview或gridview,数据从网络拉取,带上拉刷新和下拉加载更多的功能

    分析

    对于这种简单的页面来说,分析各页面不同的地方:
    1.上一个页面传入的参数:
    2.网络请求的url
    3.网络请求的部分参数(其中分批加载的每批大小和第几批这两个参数的key在整个项目中都是一样的,每批大小的value可能不一样)
    4.response数据回来后,从哪个字段中取出列表对应的数据,可能会不一样
    5.对列表数据datas的每一条,有些字段的数据需要处理,处理的方式会不一样.
    6.UI中:item内容和样式每个页面会不一样

    7.标题栏文字
    8.列表数据为空时的说明文字
    9.非第一进入时调用onShow(相当于安卓中的onResume)时,是否自动刷新页面数据

    js-页面加载逻辑全部封装在方法中:

     netUtil.requestSimpleList(that,pageIndex,action);
    

    js–page里:需要设置的都加上了todo注释,高亮显示,便于直接填内容

    var utils=require("../../utils/util.js");
    var netUtil=require("../../utils/netUtil.js");
    var viewBeans=require("../../beans/viewBeans.js");
    var infoBeans=require("../../beans/infoBeans.js");
    var API=require("../../utils/API.js");
    
    const request_firstIn = 1;
    const request_refresh = 2;
    const request_loadmore = 3;
    const request_none = 0;
    
    var app = getApp();
    var that;
    var id =0;  //页面id
    var intentDatas;
    var isFristIn = true;
    
    var needRefreshOnResume = false;//todo 页面需要自己决定
    
    Page({
      data: {
        title:'我的收藏',//todo 设置标题栏
          emptyMsg:'暂时没有内容,去别处逛逛吧',//todo 空白显示内容
          requestMethod:"POST",//todo 如果不是post,则在这里改
          urlTail:API.User.MYCOLLECTION,//todo 需补全的,页面请求的url
    
          netStateBean: new netUtil.netStateBean(),
          currentPageIndex:1,
          currentAction : 0,
          infos:[],//列表数据
      },
    
    //以下四个方法是生命周期方法,已封装好,无需改动
     onLoad: function(options) {
       that = this;
       intentDatas = options;
         if (that.data.emptyMsg != null && that.data.emptyMsg != '' ){
             that.data.netStateBean.emptyMsg = that.data.emptyMsg;
         }
        that.parseIntent(options);
       this.requestList(1,request_firstIn)
      },
      onReady: function () {
        wx.setNavigationBarTitle({
          title: this.data.title
        });
      },
      onHide:function(){
    
        },
      onShow:function(){
        if (isFristIn){
            isFristIn = false;
        }else {
            if (needRefreshOnResume){
               if (that.data.currentAction ==request_none){
                    this.requestList(1,request_refresh);//刷新
               }
            }
        }
      },
        //上拉加载更多
        onLoadMore: function(e) {
        console.log(e);
            console.log(that.data.currentAction +"---"+request_none);
         if (that.data.currentAction ==request_none){
             this.requestList(that.data.currentPageIndex+1,request_loadmore)
         }
      },
        //下拉刷新,通过onPullDownRefresh来实现,这里不做动作
        onRefesh: function(e) {
        console.log(e);
      },
    
    
    
     onPullDownRefresh:function(e){
         this.requestList(1,request_refresh);
    },
    
        //针对纯listview,网络请求直接一行代码调用
        requestList:function(pageIndex, action){
           netUtil.requestSimpleList(that,pageIndex,action)
        },
    
        //todo 滑动监听,各页面自己回调
        scroll: function(e) {
            console.log(e)
        },
        //todo 将intent传递过来的数据解析出来
        parseIntent:function(options){
    
        },
    
        //todo 设置网络参数
        /**
         * 设置网络参数
         * @param params config.params
         * @param id 就是请求时传入的id,也是成员变量-id
         */
        setNetparams: function (params) {
    
        },
    
        //todo 如果list数据是netData里一个字段,则更改此处
        getListFromNetData:function(netData){
            return netData;
        },
    
        //todo 数据的一些处理并刷新数据
        handldItemInfo:function(info){
    
        }
    })
    

    wxml中,写好空白页面,错误页面,加载更多栏

    <view class="section" style="width: 100% ;height: 100%">
    
      <scroll-view wx:if="{{!netStateBean.contentHidden}}" scroll-y="true" style="height:1300rpx;position:relative; z-index:0;" lower-threshold="50"
                   bindscrolltolower="onLoadMore" bindscrolltoupper="onRefesh" >
    
    <!--todo listview-->
    
              <view class="list_data">
                  <block wx:for-items="{{infos}}" wx:for-item="info" wx:for-index="index">
                      <navigator url="/pages/lession/{{info.classname}}?id={{info.id}}&title={{info.title}}" hover-class="">
                          <!--todo---listview: 这里写item的具体内容 -->
    
                      </navigator>
                  </block>
              </view>
    
    
    <!--todo gridview  同时js中getListFromNetData()方法返回utils.to2DimensionArr(netData,columnNum);-->
    
                  <block wx:for-items="{{infos}}" wx:for-item="info" >
                      <view class="row-container">
                          <block wx:for-items="{{info}}" wx:for-item="item">
                              <navigator url="/pages/lession/album?id={{item.id}}" hover-class="">
                                    <!--todo gridview 这里写item具体的内容-->
    
                              </navigator>
                          </block>
                      </view>
                  </block>
    
          <!--加载更多的条栏-->
              <view class="loadmore_view" wx:if="{{!netStateBean.loadmoreHidden}}" >
                  {{netStateBean.loadmoreMsg}}
              </view>
        </scroll-view>
    
        <!--空白页面-->
        <view class ="empty_view" wx:if="{{!netStateBean.emptyHidden}}"   >
            <view class="center_wrapper" >
                <view class="center_child" >
                    <icon type="info" size="45"/>
                    <view class="msg"> {{netStateBean.emptyMsg}}</view>
                </view>
            </view>
        </view>
    
        <!--错误页面-->
        <view class ="error_view" wx:if="{{!netStateBean.errorHidden}}"  >
            <view class="center_wrapper">
                <view class="center_child" >
                    <icon type="warn" size="45" />
                    <view class="msg"> {{netStateBean.errorMsg}}</view>
                    <button  class = "retrybtn"  type="warn"  loading="{{loading}}"
                             disabled="{{disabled}}" bindtap="onRetry" hover-class="other-button-hover"> 点击重试 </button>
                </view>
            </view>
        </view>
    
    </view>
    

    日志打印控制

    function log(msg){
    var isDebug = getApp().globalData.isDebug;
    if (isDebug){
        console.log(msg);
    }
    

    }

    android中的gridview在小程序里的实现

    小程序文档中只提供了一维的列表渲染示例,相对应的就是安卓中的列表listview.一维的数组,一维的UI.
    如果是实现gridview这种XY轴两个方向的延伸,数据方面需要一个二维数组,UI方法,需要两层的嵌套渲染.

    数据转换:一维数组转换成二维数组

    /**
     *
     * @param arr 原始数据,是一个一维数组
     * @param num 变成二维数组后,每个小一维数组的元素个数,也就是gridview中每行的个数
     */
    function to2DimensionArr(arr,num){
        var newArr = new Array();//二维数组
        if (arr == undefined){
            return newArr;
        }
        var subArr=null;
        for(var i =0;i<arr.length;i++){
            var item = arr[i];
            if((i%num==0) ||subArr==null){
                subArr = new Array();//内部的一维数组
                newArr.push(subArr);
            }
            subArr.push(item);
        }
        return newArr;
    }
    

    UI上嵌套渲染:

               <block wx:for-items="{{infos}}" wx:for-item="info" >
                      <view class="row-container">
                          <block wx:for-items="{{info}}" wx:for-item="albumItem">
                              <view class="row-album-item">
                                  <navigator url="/pages/lession/album?id={{albumItem.id}}" hover-class="">
                                      <image mode="aspectFill" src="{{albumItem.coverUrl}}" class="album-cover-img"/>
                                      <text class="album-name">{{albumItem.name}}</text>
                                  </navigator>
                              </view>
                          </block>
                      </view>
                 </block>
    

    效果

    1478249563128_2.png

    代码

    wxapp-devFrame

    展开全文
  • 做任何程序开发要首先找到...这里就是做微信小程序开发的全部官方文档。 知道了文档的位置,下面我们来介绍下如何做一个微信小程序开发: 第一步: 下载微信小程序开发者工具并安装,下载路径: https://mp.weix...

    做任何程序开发要首先找到其官方文档,我们先来看看其有哪些官方文档。

    微信小程序开发文档链接为:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html,如下图:

    在这里插入图片描述

    这里就是做微信小程序开发的全部官方文档。

    知道了文档的位置,下面我们来介绍下如何做一个微信小程序开发:

    第一步:

    下载微信小程序开发者工具并安装,下载路径:

    https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html

    进到下载界面后,根据自己的操作系统选择相应的链接进行下载,下载完成后进行安装。

    第二步:登录工具

    开发者工具安装完成后我们就可以将其打开,初次打开会需要用微信扫码登录,入下图,用手机微信扫一扫后确认登录就可以了。
    在这里插入图片描述

    第三步:创建一个项目

    登录成功后,如果是第一次使用该工具会弹出创建项目的窗口,如下图:
    在这里插入图片描述
    ​ 在创建过程中,如果选择的本地文件夹是个空文件夹会出来一个勾选项“在当前目录中创建quick start项目”,为方便初学者了解微信小程序的基本代码结构,请勾选此项,勾选后,开发者工具会帮助我们在开发目录里生成一个简单的 demo,如下图:
    在这里插入图片描述

    第四步:项目代码结构解释

    在这里插入图片描述
    点击开发者工具左侧导航的“编辑”,我们可以看到这个项目,已经初始化并包含了一些简单的代码文件。最关键也是必不可少的,是 app.js、app.json、app.wxss 这三个。其中,.js后缀的是脚本文件,.json后缀的文件是配置文件,.wxss后缀的是样式表文件。微信小程序会读取这些文件,并生成小程序实例。

    下面我们简单了解这三个文件的功能,方便修改以及从头开发自己的微信小程序。

    ​ 1、app.js是小程序的脚本代码。我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。调用框架提供的丰富的 API,如本例的同步存储及同步读取本地数据。

    2、​ app.json 是对整个小程序的全局配置。我们可以在这个文件中配置小程序是由哪些页面组成,配置小程序的窗口背景色,配置导航条样式,配置默认标题。注意该文件不可添加任何注释。

    3、app.wxss 是整个小程序的公共样式表。我们可以在页面组件的 class 属性上直接使用 app.wxss 中声明的样式规则。

    我们注意到,在实例程序的代码中还有2个文件夹,一个是pages,一个是utils,其中utils是放通用工具类方法的一个文件夹,pages是存放所有页面的文件夹。我们着重讲一下这个pages.

    第五步:小程序页面文件构成

    在这个示例中,我们有两个页面,index 页面和 logs 页面,即欢迎页和小程序启动日志的展示页,他们都在 pages 目录下。微信小程序中的每一个页面的【路径+页面名】都需要写在 app.json 的 pages 中,且 pages 中的第一个页面是小程序的首页。

    每一个小程序页面是由同路径下同名的四个不同后缀文件的组成,如:index.js、index.wxml、index.wxss、index.json。.js后缀的文件是脚本文件,.json后缀的文件是配置文件,.wxss后缀的是样式表文件,.wxml后缀的文件是页面结构文件。

    ​ index.wxml 是页面的结构文件:

    <!--index.wxml-->
    <view class="container">
      <view  bindtap="bindViewTap" class="userinfo">
        <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
        <text class="userinfo-nickname">{{userInfo.nickName}}</text>
      </view>
      <view class="usermotto">
        <text class="user-motto">{{motto}}</text>
      </view>
    </view>
    

    本例中使用了、来搭建页面结构,绑定数据和交互处理函数。

    ​ index.js 是页面的脚本文件,在这个文件中我们可以监听并处理页面的生命周期函数、获取小程序实例,声明并处理数据,响应页面交互事件等。

    //index.js
    //获取应用实例
    var app = getApp()
    Page({
      data: {
        motto: 'Hello World',
        userInfo: {}
      },
      //事件处理函数
      bindViewTap: function() {
        wx.navigateTo({
          url: '../logs/logs'
        })
      },
      onLoad: function () {
        console.log('onLoad')
        var that = this
        //调用应用实例的方法获取全局数据
        app.getUserInfo(function(userInfo){
          //更新数据
          that.setData({
            userInfo:userInfo
          })
        })
      }
    })
    

    index.wxss 是页面的样式表:

    /**index.wxss**/
    .userinfo {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    .userinfo-avatar {
      width: 128rpx;
      height: 128rpx;
      margin: 20rpx;
      border-radius: 50%;
    }
    
    .userinfo-nickname {
      color: #aaa;
    }
    
    .usermotto {
      margin-top: 200px;
    }
    

    页面的样式表是非必要的。当有页面样式表时,页面的样式表中的样式规则会层叠覆盖 app.wxss 中的样式规则。如果不指定页面的样式表,也可以在页面的结构文件中直接使用 app.wxss 中指定的样式规则。

    ​ index.json 是页面的配置文件:

    ​ 页面的配置文件是非必要的。当有页面的配置文件时,配置项在该页面会覆盖 app.json 的 window 中相同的配置项。如果没有指定的页面配置文件,则在该页面直接使用 app.json 中的默认配置。

    ​ logs 的页面结构

    <!--logs.wxml-->
    <view class="container log-list">
      <block wx:for-items="{{logs}}" wx:for-item="log">
        <text class="log-item">{{index + 1}}. {{log}}</text>
      </block>
    </view>
    

    logs 页面使用 控制标签来组织代码,在 上使用 wx:for-items 绑定 logs 数据,并将 logs 数据循环展开节点

     //logs.js
    var util = require('../../utils/util.js')
    Page({
      data: {
        logs: []
      },
      onLoad: function () {
        this.setData({
          logs: (wx.getStorageSync('logs') || []).map(function (log) {
            return util.formatTime(new Date(log))
          })
        })
      }
    })
    

    运行结果如下:
    在这里插入图片描述

    第六步:手机预览(只有获得AppId的才有权限预览)

    ​ 开发者工具左侧菜单栏选择"项目",点击"预览",扫码后即可在微信客户端中体验。
    在这里插入图片描述
    以上是微信小程序前端开发的基本流程,而实际上要做一个内容可以更新的小程序,单有前端开发是远远不够的,还需要后台开发。后台开发与web开发的后台基本无异,可以选择用java、php、nodejs等任一语言,有一点需要注意的是小程序后台服务器必须是https协议的,这就要求必须购买云服务器并将后台服务器设置成https服务。

    展开全文
  • 只是当时做这个系统的时候,由于需要使用java语言作为后端实现与微信小程序界面数据交互,看遍网上很多的案例基本后台都是php语言用于编写接口,几乎没找到过java作为后台语言的案例。写这篇博客只是为了帮助需要...

    基于微信小程序的培训机构系统

    前言:该系统作为本科毕业设计,可能还有很多的不足。只是当时做这个系统的时候,由于需要使用java语言作为后端实现与微信小程序界面数据交互,看遍网上很多的案例基本后台都是php语言用于编写接口,几乎没找到过java作为后台语言的案例。写这篇博客只是为了帮助需要后台使用java语言来实现的朋友。

    一、项目介绍

    微信小程序端:

    1. 小程序端管理员实现对信息模块的管理,包含课程、讲师、学员三类模块。
    2. 小程序端用户实现各类模块内容的浏览。

    Web后台管理端:

    1. Web端管理员实现对信息模块的管理;
    2. Web端讲师实现对培训机构学员课程成绩打分等功能;
    3. Web端学员实现对培训机构课程的报名、退选以及课程成绩查看等功能;

    二、相关技术

    1. 微信小程序(js、css前端基础):前端小程序页面;
    2. SSM框架(Spring+SpringMVC+Mybatis):微信小程序界面需要调用的接口以及后台的管理系统;
    3. Maven:项目管理必备的技术;
    4. Shiro框架:保证系统安全的框架;
    5. Bootstrap前端框架:Web后台管理端的后台界面;

    三、项目配置搭建
    链接:https://blog.csdn.net/qq_38285537/article/details/91326332

    四、系统结构
    三层模块:客户端、服务端、数据端

    五、界面展示
    管理员默认账号为admin,密码123,登录进入管理导航界面;
    用户登录界面
    在这里插入图片描述
    首页管理导航,实现对学员、讲师、课程进行增删改查的操作。
    在这里插入图片描述
    添加学员表单界面
    在这里插入图片描述
    学员名单表格页面使用表格的形式进行显示学员的信息数据。由于微信小程序展示的数据界面比较小,通过设计成可以上下左右滑动表格的方式来查看数据,可以使得小程序也展现表格形式的页面。
    在这里插入图片描述
    在这里插入图片描述
    修改学员界面
    在这里插入图片描述
    用户首页界面,登录账号:1001,密码:123
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    热门课程内容展示
    在这里插入图片描述
    在这里插入图片描述
    我的功能界面
    在这里插入图片描述
    Web端后台管理模块
    管理员模块:课程管理、学员管理、课程管理
    在这里插入图片描述
    讲师模块:课程成绩打分,查看教授课程
    在这里插入图片描述
    学员模块:对课程进行报名以及退选,查看报名课程,查看讲师给自己报名课程的评分;
    在这里插入图片描述

    本毕设系统三个月陆陆续续所完成,也花费了大量的时间和经历,下面提供源码进行参考学习。

    源码下载地址:

    • 该系统源代码上传gitee平台供参考(求Star):https://gitee.com/tangjiadong/Training-master

    本博客属于个人原创,转载请注明出处;
    本系统还要很多不足的地方,由于毕设时间的限制,实现就好;
    作者:CodeTang

    展开全文
  • 从今天开始,为大家开一门连载课程 ——《微信小程序开发入门》。 2011 年,腾讯公司新的即时通讯社交软件微信正式上线,凭借其新颖的设计风格和良好的使用体验,微信很快就获得了大量的用户。据腾讯公司官方信息,...

    从今天开始,为大家开一门连载课程 ——《微信小程序开发入门》。

    2011 年,腾讯公司新的即时通讯社交软件微信正式上线,凭借其新颖的设计风格和良好的使用体验,微信很快就获得了大量的用户。据腾讯公司官方信息,截止到 2018 年3月份,微信成为中国首个月活跃用户数超过 10 亿的应用软件。在 2018 年,微信小程序的每日活跃账户数量迅速增加,用户的平均每日访客量增加了 54% 。

    本场课程将从技术方面讲解微信小程序的开发,面向的对象是想入门微信小程序开发的小白,用户通过本课程的学习,可以入门微信小程序开发。

    本课程将带领大家入门微信小程序开发,并且以《微海院》小程序项目为主导,贯穿整个课程始终,从项目入手,做到学以致用。

    本课程您将学到如下内容:

    • 了解如何注册微信小程序及发布小程序的流程
    • 知道微信小程序的各种准备工作(域名备案、SSL 证书等)
    • 掌握微信 Web 开发者工具的使用
    • 基本掌握微信小程序官方框架 WeUIfor 小程序的使用
    • 基本掌握微信小程序的基本组件及 API 的使用
    • 基本掌握小程序后端程序(PHP),打通前后端通信

    enter image description here

    据腾讯公司2019年发布的《腾讯公布二零一八年第四季度及全年业绩》显示,微信小程序覆盖的服务行业超过200个,日活跃的账户数增长快速,用户的日均访问量同比增长达到54%。不难发现,微信小程序受到了越来越多的用户和开发者的青睐。

    enter image description here

    微信小程序具有跨平台、流量大、成本低、轻应用、高体验的特点,同时还可跨越安卓和IOS平台,降低开发成本和门槛;使用体验与原生的应用程序相似,并且可以与微信公众号、应用程序相互打通;用户无需下载注册,用完即走,不占内存,使业务变得触手可及。

    扫码进入Chat:
    在这里插入图片描述

    下一篇:微信小程序开发入门(连载)—— 开发前的准备工作


    作者:戴翔
    电子邮箱:daixiangcn@outlook.com
    简介:中华人民共和国公民,中国共青团员,CSDN博客专家,秦淮区疾控中心托管社会公益组织指南针工作室志愿者,在校大学生,微信小程序《约车吗》、《指南针微公益》总工程师。


    展开全文
  • 廖伟国 谢杰新 胡婉玲 卢晓惠摘 要:在开发校园资讯小程序的后台时,面临如何选择后台开发语言,经过多方比较,决定选择WeiPhp作为小程序的后台开发语言,目的是为了降低项目开发难度,使用更加简便。关键词:WeiPhp...
  • php 微信开发组件 wechat 公众号 支付宝 小程序开发框架
  • 微信小程序商城 商城框架的制作 讲解商城小程序首页模块的制作,包含商城框架的制作、顶部普通广告图片、顶部轮播广告、快捷菜单、最新通知、最新产品、精品推荐等元素的制作,最后介绍销售排行的制作。本章主要应用...
  • 微信小程序开发

    2016-12-02 18:34:20
    微信小程序开发学习js相关的知识1 网站上了解html ...微信小程序开发流程1 下载调试工具2 通读一遍小程序开发文档3 参考文档创建项目开发的目标—-和h5的页面类似开机动画页start 首页需要呈现的数据index
  • 微信小程序开发尝试

    千次阅读 2016-12-11 20:17:47
    微信小程序开发体验
  • 开发前必读简要 ...微信小程序开发上线(发布)步骤 这篇帖子将简单的介绍基本的步骤,以便新手们建立一个基本的印象;| 链接 微信小程序新手入门宝典 为了方便大家了解并入门微信小程序,我将一些可能会需
  • 微信小程序开发实战

    千次阅读 2019-08-04 15:12:40
    微信小程序开发实战 ================================================= cemike@126.com 本文介绍了作者开发Swing English微信小程序的实践。从实践经验提出微信小程序开发的最佳实践步骤和常见问题的解决方法。...
  • 拼序网(小程序制作服务商) 做任何程序开发要首先找到其官方文档,我们先来看看其有哪些官方文档。...知道了文档的位置,下面我们来介绍下如何做一个微信小程序开发: /**************************...
  • 微信小程序有所不同了,它目前还是比较麻烦的,官方是没有模板的,是属于有着自己的后台的,所以微信小程序的内容需要自己设计和开发。一系列操作完成之后是利用小程序后台进行发布。 所以它的一
  • 微信小程序框架集合

    万次阅读 多人点赞 2017-01-15 18:57:43
    weui-wxss ★852 - 同微信原生视觉体验一致的基础样式库Wa-UI ★122 - 针对微信小程序整合的一套UI库wx-charts ★105 - 微信小程序图表工具wemark ★85 - 微信小程序Markdown渲染库WeZRender ★36 - 微信小程序...
  • 微信小程序-极客社区 使用 1、服务器端使用开源项目wordpress,需要PHP+MYSQL环境,把server目录下文件拷贝至虚拟主机,修改wp-config.php的数据库配置信息, 批量替换server/sql目录下的sql文件中的域名为你的域名并...
  • 根据上面的布局分析,我们会产生基础的框架,代码示例如下: <view><!—第1层-开始--> <image></image><!—第2层--> <view><!—第2层--> <view>珀莱雅水动力...
  • onLoad = function () { var self = this; wx.login({ success: function (data) { wx.getUserInfo({ success: function (userinfo) { self.setData({userInfo: userinfo}); } }); } ...}
  • 微信小程序开发入门

    2019-06-10 23:30:03
    2011 年,腾讯公司新的即时通讯社交软件微信正式上线,凭借其新颖的设计风格和良好的使用体验,微信很快就获得了大量的用户。...本场 Chat 将从技术方面讲解微信小程序开发,面向的对象是想入门微信小程序...
  • 微信小程序开发入门教程 含视频 有源码

    万次阅读 多人点赞 2017-07-03 10:31:18
    微信小程序开发入门教程  做任何程序开发要首先找到其官方文档,我们先来看看其有哪些官方文档。 微信小程序开发文档链接为:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html,如下图:    ...
  • 最近开发了一个PHPCMS微信小程序接口模块,基本实现了PHPCMS后台数据的傻瓜式输出,极大的提高了用PHPCMS作为后端来开发微信小程序的效率。 分享一个PHPCMS列表页接口的写法,有疑问的朋友欢迎随时给我留言交流,...
  • 前俩章中我们学会了怎么搭建一个微信小程序框架以及显示一个文章列表,这篇文章我将讲解列表的网络请求以及网络数据的对接。 首先找到我们的index.js文件,然后看看微信小程序的网络请求文档很轻松的就可以找到...
  • Wa-UI ★122 - 针对微信小程序整合的一套UI库 wx-charts ★105 - 微信小程序图表工具 wemark ★85 - 微信小程序Markdown渲染库 WeZRender ★36 - 微信小程序Canvas增强组件 wetoast ★21 - 仿照微信小程序...
  • 原文: ...小程序获取用户的头像昵称openid之类 第一种 使用wx.getUserInfo直接获取微信头像,昵称 wx.getUserInfo({ success: function (res) { that.setData({ nick...
  • 程序调试主要有三大功能区:模拟器、调试工具和小程序操作区模拟器模拟器模拟微信小程序在客户端真实的逻辑表现,对于绝大部分的 API 均能够在模拟器上呈现出正确的状态。编译代码点击工具左下角的编译按钮,可以...
  • 在这里我就把我是如何利用API开发微信小程序的过程写成教程,教大家快速上手体验一次微信小程序开发。 补充: 之前忘了把源码发上来,完成之后就已经放在Github上了 点我下载>> 在开始之前我们先来看下成品的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,248
精华内容 4,499
关键字:

php微信小程序开发框架

微信小程序 订阅