美文网首页
小程序学习笔记

小程序学习笔记

作者: 冰风v落叶 | 来源:发表于2019-05-23 16:52 被阅读0次

    一、全局框架

    小程序的主体由三个文件组成:app.jsapp.jsonapp.wxss
    小程序主体.png
    一个小程序的页面由四个文件组成:.js.json.wxss.wxml
    小程序的某个页面.png
    1. app.json 是当前小程序的全局配置,定义了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等,JSON 文件中无法使用注释,加注释会报错。

    2. app.js中会产生一个App实例,用于监听小程序的生命周期、错误监听、页面不存在监听,整个小程序只有这一个App实例,全部页面共享,可以通过getApp()方法获取此全局唯一的App实例。(可以在此实例上保存共用的数据,以便各个界面共用)

    // xxx.js
    const appInstance = getApp()
    console.log(appInstance.globalData)
    
    1. app.wxss,用来描述WXML的组件样式,具有CSS的大部分特性。

    2. project.config.json是项目配置文件,可以定义小程序和云开发的目录位置,可以配置个性化选项等等。

    二、小程序的渲染层和逻辑层

    小程序的运行环境分成渲染层逻辑层,其中 WXML 模板WXSS 样式工作在渲染层JS 脚本工作在逻辑层

    小程序的渲染层和逻辑层分别由2个线程管理:

    • 渲染层的界面使用了WebView 进行渲染,一个小程序存在多个界面,所以渲染层存在多个WebView线程。

    • 逻辑层采用JsCore线程运行JS脚本。

    • 这两个线程的通信会经由微信客户端做中转,逻辑层发送网络请求也经由微信客户端转发,小程序的通信模型下图所示。


      小程序通信模型

    三、 程序与页面

    微信打开小程序流程:

    • 首先微信在打开小程序之前,会把小程序的代码包下载到本地。

    • 然后通过 app.json 的 pages 字段就可以知道你当前小程序的所有页面路径,pages字段的第一个就是小程序的首页。

    • 微信吧首页的代码装载进来,通过底层机制,渲染出来首页。

    小程序启动流程:

    • 小程序启动之后,在 app.js 定义的 App 实例的 onLaunch 回调会被执行。(整个小程序只有这一个实例,全部页面共享。)

    • 微信会先根据首页的.json文件生成一个界面。(.json文件定义了导航栏的颜色和文字等信息)

    • 然后装载首页的.wxss.wxml文件。

    • 最后装载首页的.js文件,.js文件有一个Page实例,小程序会根据Page实例中的data数据和首页的.wxml文件,一起渲染出最终的结构,这就是你看到的小程序首页的样子。(渲染完成后,Page实例会受到一个onLoad回调)

    四、小程序运行机制

    五、小程序更新机制

    六、事件系统

    七、自定义组件

    自定义组件
    1. 已自定义一个上拉加载组件为例,下图是一个自定义的上拉加载组件:


      上拉加载组件.png
    2. 组件由四个文件组成:json、wxml、wxss、js,要写自定义组件,需要在json文件中进行自定义组件声明

    {
      "component": true
    }
    
    1. 在自定义组件的 js 文件中,需要使用 Component 来注册组件,并提供组件的属性定义、内部数据和自定义方法。
    // components/load-more/index.js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
          hasMore: {
            type: Boolean,
            value: false
          },
          // 加载中的显示文本
          loadingText: {
            type: String,
            value: '加载中...'
          },
          // 加载失败的显示文本
          failText: {
            type: String,
            value: '加载失败, 请点击重试!'
          },
          // 没有更多后的显示文本, 默认没有则隐藏加载更多控件
          finishText: {
            type: String,
            value: ''
          },
          // 列表渲染延时, 默认为 500 ms, 我在开发工具中测试列表渲染速度时快时慢, 可根据实际使用中界面复杂度自行调整
          // ps 如果能监听setData() 渲染结束的话则可以不需要延时 
          listRenderingDelay: {
            type: Number,
            value: 500
          }
      },
    
      /**
       * 组件的初始数据
       */
      data: {
        showThis: false,
        text: '',
        showIcon: false,
        isLoading: false
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
    
        //加载更多的入口方法, 直接在page中使用时请在onReachBottom() 方法中调用这个方法, 并实现loadMoreListener方法去获取数据
        loadMore: function() {
          if(!this.properties.hasMore){
            console.log('load more finish')
            return
          }
          if(this.data.isLoading) {
            console.log('loading ...')
            return
          }
          this.setData({
            isLoading: true
          })
          this.triggerEvent('loadMoreListener')
        },
        //加载完成, 传入hasMore 
        loadMoreComplete: function(data) {
            var hasMore = data.curPage < data.pageCount && data.pageCount != 1
            var text = '', showThis = false, showIcon = false
    
            if (hasMore) {
              showIcon = true
              showThis = true
              text = this.properties.loadingText
            } else if (this.properties.finishText.length>0) {
              text = this.properties.finishText
              showThis = true
            }
            this.setData({
              hasMore: hasMore,
              text: text,
              showIcon: showIcon,
              showThis: showThis
            })
            //界面渲染延迟, 避免列表还未渲染完成就再次触发 loadMore 方法
            setTimeout(function(){
              this.setData({
                isLoading: false
              })
            }.bind(this), this.properties.listRenderingDelay)
        },
        // 加载失败
        loadMoreFail: function() {
          this.setData({
            showIcon: false,
            text: this.properties.failText
          })
    
          //界面渲染延迟, 避免列表还未渲染完成就再次触发 loadMore 方法
          setTimeout(function(){
            this.setData({
              isLoading: false
            })
          }.bind(this), this.properties.listRenderingDelay)
        },
        //点击 loadmore 控件时触发, 只有加载失败时才会进入页面回调方法
        clickLoadMore: function() {
          if(this.data.text != this.properties.failText) return
          this.setData({
            showIcon: true,
            text: this.properties.loadingText,
            isLoading: true
          })
          this.triggerEvent('clickLoadMore')
        }
      }
    })
    
    
    1. 剩下的就跟下普通的页面一样了,在wxml中编写组件模板,在wxss中编写样式。

    注意:在组件wxss中不能使用ID选择器、属性选择器和标签名选择器。

    使用自定义组件
    1. 将组件文件夹复制到自己的小程序中

    2. 在需要用到此组件的页面A的json文件中进行声明,提供此组件的标签名和文件路径:

    {
      "usingComponents": {
        "load-more":"../../components/load-more/index"
      }
    }
    
    1. 把此组件放到页面A的wxml文件的合适的位置
    <load-more id="loadMoreView" bindloadMoreListener='loadMoreListener' bindclickLoadMore='clickLoadMore'></load-more>
    
    1. 在页面A的js文件中,初始化此组件
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
       //loadMoreView是在Page之外的定义的变量(var loadMoreView)
       //拿到loadMoreView后就可以调用此组件里的方法
        loadMoreView = this.selectComponent("#loadMoreView")
      },
    
    1. 在页面A的js文件中,在触底事件中调用组件的loadMore方法
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
        if (this.data.isLoading == false) {
          this.setData({
            currentPage: this.data.currentPage + 1
          })
          loadMoreView.loadMore()
        }
      },
    
    1. 在页面A的js文件中,实现两个回调:
    //触底事件时,调用了loadMore函数,loadMore函数会调用loadMoreListener函数
    loadMoreListener: function (e) {
        this.requestListData(this.data.currentPage)
    },
    //当加载失败时,会出现加载更多视图,
    //点击加载更多视图,会调用此函数
    clickLoadMore: function (e) {
        this.requestListData(this.data.currentPage)
    },
    
    1. 每个自定义组件的使用方法都不相同,可以先看作者提供的使用方法和源码,根据自己的实际情况使用或者微调。

    八、插件

    九、 需要注意的地方

    1. wx:key,wx:key值是否唯一,会控制组件是否重新创建

    • 当wx:key=""是唯一的值时,数据改变触发渲染层重新渲染时,会校正key唯一的组件,保持他们的状态,提高渲染效率,而不会重新创建。

    • 当wx:key没有设置或者不唯一时,数据改变触发渲染时,会重新创建组件,会丢失原先的状态。(如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。

    设置wx:key唯一,有两种方式:

    • wx:key可以是数组的item的某个属性,需要确保此属性是唯一的字符串或者数字,并且不能动态改变。

    • wx:key可以是保留关键字*this,代表在for循环中的item本身,这种表示需要item是一个唯一的字符串或者数字。

    2. 下拉刷新

    • 通过.json中的enablePullDownRefresh为true来开启用户手动刷新

    • 通过API的wx.startPullDownRefresh()可以自动触发下拉刷新

    • 通过API的wx.stopPullDownRefresh()来停止下拉刷新

    • 通过app.jsonwindowbackgroundTextStyle来控制样式,dark和light两种可以选择。

    • 通过.js中的onPullDownRefresh()方法,来监控下拉刷新操作

    **3. **

    十、微信小程序开发者文档,遇到问题及时查询官方文档和官方Demo

    相关文章

      网友评论

          本文标题:小程序学习笔记

          本文链接:https://www.haomeiwen.com/subject/vhrhjqtx.html