小程序相关整理 (编辑中...)

小程序相关整理

小程序简介

小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。小程序开发主要面对的是两大操作系统ios和android的微信客户端; MVVM是关键;


小程序代码构成

###文件支持

支持wxml,wxss,js,json,wxs以及图片文件的预览;

###JSON 配置文件

在小程序中JSON是用于静态配置;

app.jsonproject.config.jsonpages/logs目录下还有一个logs.json;

  • 小程序配置 app.json

    • 小程序的全局配置,包括所有页面路径,界面表现,网络超时时间,底部tab;
    • pages 字段: 描述当前小程序所有页面路径,这是为了让wx客户端知道当前你的小程序页面定义在那个目录;
    • window 字段: 定义小程序所有页面的顶部背景颜色,文字颜色定义等;
    • 详情见 微信官方文档全局配置
  • 工具配置 project.config.json

    • 类似于androidev 中的gradlewrapper ,同步化的个性化配置;
    • 详情见 微信官方文档项目配置文件
  • 页面配置 page.json

    • 指的是 pages/logs中的logs.json这类和小程序页面相关的配置;
    • 可以让开发者独立定义每个页面的一些属性,如顶部颜色,是否允许下拉刷新等,app.json是定义整个小程序的配置;
    • 详情见 微信官方文档页面配置文件

###WXML 模板文件 weixin markup language

在小程序中WXML相当于网页开发中的HTML;不同点在于:

  • 标签名字不同 使用的是单独包装好的标签;
  • 添加 wx:if这样的属性以及类似于{ {}}表达式;
    • MVVM的开发模,将渲染和逻辑分离,数据绑定;
    • 不让js直接操控dom,通过一种模板语法描述状态和界面结构的关系;
    • 详情见 微信官方文档WXML

###WXSS 样式文件 weixin style sheet

类似于网页开发中的css; 扩展:

  • 尺寸单位; (iphone6位视觉稿的标准)
    • wxss 在底层支持新的尺寸单位 rpx;(responsive pixel)可以根据屏幕宽度进行自适应;
  • 样式导入;
    • @import 导入外联样式表, 外联样式表的相对路径;
    • 提供全局样式和局部样式; 可定义一个app.wxss表示全局样式;局部样式 page.wxss仅对当前页面生效;
  • 内联样式
    • 组件上使用style和class属性控制组件的样式;
      • style : 静态的样式统一写到class中;而style接受动态的样式,在运行时会进行解析;
      • class : 用于指定样式规则,属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.;样式类名间用空格隔开;
      • js 中选择器基本支持;
  • 详情见 微信官方文档WXSS
	
	/** common.wxss **/
	.small-p {
	  padding:5px;
	}

	/** app.wxss **/
	@import "common.wxss";
	.middle-p {
	  padding:15px;
	}

###wxs 小程序脚本语言; weixin script

可构建出页面的结构;

  • 不依赖与运行时的基础库版本,可以在所有版本的小程序汇总运行;
  • wxs的运行环境不能调用其他javascript文件中定义的函数;
  • wxs函数不能作为组件的事件回调;
  • 详情见 微信官方文档Wxs

	// page.js
	Page({
	  data: {
	    array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
	  }
	})

	
	
	
	var getMax = function(array) {
	  var max = undefined;
	  for (var i = 0; i < array.length; ++i) {
	    max = max === undefined ?
	      array[i] :
	      (max >= array[i] ? max : array[i]);
	  }
	  return max;
	}
	
	module.exports.getMax = getMax;
	
	
	
	 {
    {m1.getMax(array)}} 

###JS 脚本逻辑文件 javascript

用于和用户交互;

  • 可用js调用小程序提供的API,调起微信提供的能力;
  • 详情见 微信官方文档API

小程序宿主环境

小程序相关整理 (编辑中...)_第1张图片

小程序的运行环境可分为 渲染层(View)和逻辑层(App Service); wxml和wxss工作在渲染层,js脚本工作在逻辑层; 分别由两个线程管理,渲染层的界面使用webview 进行渲染;逻辑层采用JsCore线程运行JS脚本;

小程序存在多个界面,渲染层存在有多个webview线程,这两个线程的通信会经由微信客户端(Native代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发;

程序和页面

  • wx客户端 在打开小程序之前,会把整个小程序的代码包下载到本地;

  • app.json 的pages字段可以知道当前小程序的所有页面路径; wx客户端把首页的代码装载进来,通过底层的一些机制,渲染整个首页;

    • 第一个页面就是小程序的首页;
  • 小程序启动后, app.js 定义的app实例 的onLaunch回调会被执行; 整个小程序只有一个app实例 是全部页面共享的;

    • app.json 中定义的路径中都包含了4种文件,分别为js,json,wxml,wxss 首先wx客户端会根据json配置生成一个界面,配置整体页面的颜色和文字;
    • 然后wx客户端根据 wxml和wxss文件装载样式;
    • 最后wx客户端 装载 js文件;
  • 页面 js文件中 Page 是一个页面构造器,这个构造器就生成了一个页面; 在生成页面时,小程序框架会把data数据和index.wxml 一起渲染出最终的结构; 在渲染完界面之后,页面实例就会收到一个onLoad 的回调,可以在这个回调中处理你的逻辑;

###目录结构

app : 描述整体程序;
page : 描述各自页面;

一个小程序主体部分构成: app.js, app.json, app.wxss;

一个小程序页面构成: js, wxml, json, wxss; 描述页面的四个文件必须具有相同的路径和文件名;

sitemap 小程序内搜索

小程序根目录下 sitemap.json 文件用来配置小程序及其页面是否允许被微信索引;
默认是都能被索引;


小程序框架 (逻辑层 + 视图层)

###多个简便写法

  • behaviors 的使用 ,pages可引用behaviors用来让更多的页面有相同的数据字段和方法;

小程序相关整理 (编辑中...)_第2张图片

微信官方文档 behaviors

  • Component 构造器构造页面 ,适合于复杂的页面; Page构造器适用于简单的页面构建;

小程序相关整理 (编辑中...)_第3张图片

小程序页面生命周期

###页面路由

框架进行页面的路由管理,以栈的形式维护了当前的所有页面;

路由方式 页面栈表现 触发时机 路由前页面 路由后页面
初始化 新页面入栈 小程序打开的第一个页面 onLoad, onShow
打开新页面 新页面入栈 调用 API wx.navigateTo 使用组件 onHide onLoad, onShow
页面重定向 当前页面出栈,新页面入栈 调用 API wx.redirectTo 使用组件 onUnload onLoad, onShow
页面返回 页面不断出栈,直到目标返回页 调用 API wx.navigateBack 使用组件用户按左上角返回按钮 onUnload onShow
Tab切换 页面全部出栈,只留下新的tab页面 调用 API wx.switchTab 使用组件 用户切换 Tab 各种情况请参考下表
重加载 页面全部出栈,只留下新的页面 调用 API wx.reLaunch 使用组件 onUnload onLoad, onShow

getCurrentPages()获取当前页面栈;

tips:

  • navigateTo,redirectTo 只能打开非tabBar页面;
  • switchTab 只能打开tabBar页面;
  • relaunch 可以打开任意页面;
  • 页面底部的tabBar由页面决定,即只要是定义为tabBar的页面,底部都有tabBar;
  • 调用页面路由自带的参数可以在目标页面的onLoad中获取;

###模块化 (相当于library或者工具类)

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

  • exports 是 module.exports 的一个引用,因此在模块里面随意更改exports 的 指向 会造成未知的错误; 推荐使用module.exports来暴露接口; 在使用这些模块文件中,使用require将公共代码引入;
  • 小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中,或者使用小程序支持的 npm 功能。

	// common.js
	function sayHello(name) {
	  console.log(`Hello ${name} !`)
	}
	function sayGoodbye(name) {
	  console.log(`Goodbye ${name} !`)
	}
	
	module.exports.sayHello = sayHello
	exports.sayGoodbye = sayGoodbye
	
	---------------------
	var common = require('common.js')
	Page({
	  helloMINA: function() {
	    common.sayHello('MINA')
	  },
	  goodbyeMINA: function() {
	    common.sayGoodbye('MINA')
	  }
	})

###微信原生API

  • 类型
    • 事件监听API

      • on开头的api 用来监听某个事件是否触发,这类api接受一个回调函数作为参数,当事件触发时会调用这个回调函数,并将相关数据以参数形式传入;
      • wx.onCompassChange
    • 同步API

      • Sync结尾的api 通过函数返回值直接获取,执行出错会抛出异常; 需要try catch;
      • wx.setStorageSync
    • 异步API

      • 这类api 通常接受一个Object类型参数,这个参数都支持按需指定以下字段来接受接受调用结果;
        • Object参数: success,fail,complete,其他;
        • 回调函数的参数: success,fail,complete函数调用时传入一个Object类型参数,包括以下字段: errMsg:String,errCode:number,其他;
      • 异步api返回promise
        • 2.10.2 ,异步api支持callback & promise 两种调用方式;当接口参数Object对象中不包含success/fail/complete时将默认返回promise,否则仍按回调方式执行,无返回值;
        • 部分接口如 downloadFile, request, uploadFile, connectSocket, createCamera(小游戏)本身就有返回值, 它们的 promisify 需要开发者自行封装。
        • 当没有回调参数时,异步接口返回 promise。此时若函数调用失败进入 fail 逻辑, 会报错提示 Uncaught (in promise),开发者可通过 catch 来进行捕获。
        • wx.onUnhandledRejection 可以监听未处理的 Promise 拒绝事件。

	wx.login({
	  success(res) {
	    console.log(res.code)
	  }
	})

	
	wx.chooseImage({
	  success(res) {

	    console.log('res:', res)
	  }
	})
	
	
	wx.chooseImage().then(res => console.log('res: ', res))

###事件系统

  • 视图层到逻辑成的通讯方式;
  • 可以绑定在组件上,当达到触发事件,执行逻辑层中对应的事件处理函数;
  • 事件对象可以携带额外信息,如id,dataset,touches;

使用方式:

组件中绑定一个事件处理函数; bindtap 在页面对应的page中找到对应的事件处理函数; 后期可以改为 bind:tap

wxs函数响应事件:

wxs函数接受2个参数,第一个是event,在原有的event的基础上加event.instance对象; 第二个参数是ownerInstance,和event.instance一样是一个ComponentDescriptor对象;

event.instance 表示触发事件的组件的ComponentDescriptor实例;
ownerInstance 表示的是触发事件的组件所在的组件的 ComponentDescriptor实例;如果触发事件的组件是在页面内的,则表示的是页面实例;

wxs运行在视图层(webview),需要有一个机制和逻辑层开发者(App Service)的代码通信,ComponentDescriptor 的callMethod 是wxs里面调用逻辑层(appservice)定义的方法;

WxsPropObserver 是逻辑层(appservice)调用wxs逻辑的机制; wxs函数必须由{ {}}括起来;当 prop 的值被设置 WXS 函数就会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次WxsPropObserver的函数。

	--------
	
	 Click me! 
	**注:绑定的WXS函数必须用{
    {}}括起来**
	
	--------

	function tapName(event, ownerInstance) {
	  console.log('tap wechat', JSON.stringify(event))
	}
	module.exports = {
	  tapName: tapName
	}

	//`change:prop`是在prop属性被设置的时候触发wxs函数;
	
	
	
	module.exports = {
	    touchmove: function(event, instance) {
	        console.log('log event', JSON.stringify(event))
	    },
	    propObserver: function(newValue, oldValue, ownerInstance, instance) {
	        console.log('prop observer', newValue, oldValue)
	    }
	}

	---------

	//阻止事件冒泡 点击内部只有handTap3和handTap2会响应;
	
	  outer view
	  
	    middle view
	    
	      inner view
	    
	  
	

	//互斥事件,点击内部 handleTap3和handleTap2会响应;点击middle,响应handTap2和handTap1;
	
	  outer view
	  
	    middle view
	    
	      inner view
	    
	  
	

	//捕获事件,点击内部 hand2 -> hand4 -> hand3 ->hand1
	
	  outer view
	  
	    inner view
	  
	
  • 事件分类

    • 冒泡事件 当一个组件上的事件被触发后,该事件会向父节点传递;
      • 包括触摸,点击,动画等; touchstart,touchmove,touchcancel,touchend,tap,longpress,longtap,transitionend,animationstart,animationiteration,animationend,touchforcechange;
    • 非冒泡事件 当一个组件上的事件被触发后,该事件不会向父节点传递;
    • 绑定并阻止事件冒泡 ,除bind外,也可以用catch绑定事件; catch 会阻止事件向上冒泡;
    • 互斥事件绑定 ,mut-bind 如果事件冒泡到其他节点上,其他节点的mut-bind绑定函数不会被触发,但bind绑定和catch的绑定函数依旧会被触发;
    • 事件的捕获阶段,触摸类事件支持捕获阶段,捕获阶段位于冒泡阶段之前,且在捕获阶段中事件到达节点的顺序与冒泡阶段刚好相反; capture-bind,capture-catch后者将中断捕获阶段和取消冒泡阶段;
  • 事件对象

触发事件时,逻辑层绑定该事件的处理函数会受到一个事件对象,BaseEvent / customEvent(detail) / touchevent(touches/changedTouches) ; 组成:

  • type : 事件类型;
  • timeStamp : 页面打开到触发事件所经过的毫秒数;
  • target : 触发事件的源组件的一些属性值集合; id/dataset (冒泡)
  • currentTarget : 事件绑定的当前组件; id/dataset
    • dataset : wxml 自定义数据以data-开头,连字符写法最后会转为驼峰写法;
  • mark : 识别具体触发事件的target节点; 可承载一些自定义数据(类似于dataset) ,冒泡路径的mark会被合并并返回;
    • mark和dataset很相似,区别在于: mark会包含从触发事件的节点到根节点上所有的mark:属性值; 而dataset仅包含一个节点的data-属性值;
    • 如果存在同名的mark,父节点的mark会被子节点的mark覆盖;
    • 自定义组件中接受事件,mark不包含自定义组件外的节点mark;
    • 不同于dataset, 节点的mark不会做连字符和大小写转换;

	 DataSet Test 
	
	Page({
	  bindViewTap:function(event){
	    event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
	    event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
	  }
	})

	---------

	
	  
	
		
	Page({
	  bindViewTap: function(e) {
	    e.mark.myMark === "last" // true
	    e.mark.anotherMark === "leaf" // true
	  }
	})

###组件

组件时视图层的基本组成单元;组件包括一个开始标签和结束标签,属性用来修饰这个组件,内容在两个标签之间;

属性类型: boolean,number,string,array,object,eventHandler,any;

公共属性:

  • id String 组件的唯一标志;
  • class String 组件的样式类;wxss
  • style String 组件的内联样式;
  • hidden boolean 组件是否显示;
  • data-* any 自定义属性;
  • bind*/catch* EventHandler 组件的事件;

###动画

  • Css渐变,Css动画
    • 监听 (都不是冒泡事件)
      • bindtransitionend(CSS 渐变结束或wx.createAnimation 结束一个阶段)
      • bindanimationstart(CSS 动画开始)
      • bindanimationiteration(CSS 动画结束一个阶段)
      • bindanimationend( CSS 动画结束)
  • 关键帧动画 替换wx.createAnimation
    • this.animate接口 this.animate(selector, keyframes, duration, callback)
      • selector :String 选择器(selectorQuery.select选择器样式)
      • keyframes :Array 关键帧;
      • duration :Number 动画持续时长ms;
      • callback :Function (nullable) 动画完成后的回调函数;
      • ScrollTimeline 参数 (仅支持scroll-view),绑定滚动元素;
    • this.clearAnimation(selector, options, callback) 清除属性;
      • options :Object 需要清除的属性,不填写则全部清除;
  • 高级动画(属性动画) wxs响应事件方式可以通过使用wxs来响应事件的方法动态调整节点的style属性; 不断变更style属性可做到动画效果; 推荐将页面的setData改为自定义组件中的setData提升性能;

	this.animate('#container', [
	    { opacity: 1.0, rotate: 0, backgroundColor: '#FF0000' },
	    { opacity: 0.5, rotate: 45, backgroundColor: '#00FF00'},
	    { opacity: 0.0, rotate: 90, backgroundColor: '#FF0000' },
	    ], 5000, function () {
	      this.clearAnimation('#container', { opacity: true, rotate: true }, function () {
	        console.log("清除了#container上的opacity和rotate属性")
	      })
	  }.bind(this))
	
	  this.animate('.block', [
	    { scale: [1, 1], rotate: 0, ease: 'ease-out'  },
	    { scale: [1.5, 1.5], rotate: 45, ease: 'ease-in', offset: 0.9},
	    { scale: [2, 2], rotate: 90 },
	  ], 5000, function () {
	    this.clearAnimation('.block', function () {
	      console.log("清除了.block上的所有动画属性")
	    })
	  }.bind(this))

###重启策略和更新机制

重启策略

pages 对应的json文件中配置(也可以配置在app.json的window字段中),指定restartStrategy配置项,使得某个页面退出后,下次A类场景(不包括重定向和冷启动下带path跳入的场景) 的冷启动可以回到这个页面;

注意: 但不包括退出过久的情况,因为存在退出状态的保存中有expireTimeStamp 字段哟用户超时丢弃数据;


	{
		"restartStrategy": "homePage"
	}

  • homePage: (默认值)如果从这个页面退出小程序,下次将从首页冷启动
  • homePageAndLatestPage: 如果从这个页面退出小程序,下次冷启动后立刻加载这个页面,页面的参数保持不变(不可用于 tab 页)

退出状态 : 类似于android的保存状态 ,小程序可能销毁时调用onSaveExitState保存页面状态,下次启动时刻通过exitState获得这些数据;

onSaveExitState 返回值包括两项: data:Any,expireTimeStamp:Number(默认当前时刻+1天)

更新机制

  • 未启动时更新

wx client会有若干个时机检查本地缓存的小程序有没有更新版本,如果有会静默更新; 最差的情况下 发布之后24小时内更新;

  • 启动时更新

使用 wx.getUpdataManagerApi

自定义组件

类似于页面,一个自定义组件由 json,wxml,wxss,js ;

要编写一个自定义组件, 首先需要在json文件中进行自定义组件声明(将 component 字段设为true 可将一组文件设为自定义组件;)

	
	{
	  "component": true
	}

wxml 文件中加入组件样式, 在wxss文件中加入组件样式;

  • 在组件wxss 中不应使用id选择器,属性选择器和标签名选择器,使用class选择器;
  • 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,避免使用;
  • 子元素选择器(.a > .b)只能用于view组件和其子节点之间,用于其他组件会导致非预期情况;
  • 继承样式,如font,color,会从组件外继承到组件内;
  • 除继承样式外,app.wxss中的样式,组件所在页面的样式对自定义组件无效(除非更改组件样式隔离选项)
    • 默认情况下,自定义组件的样式只受到自定义组件的wxss的影响,除非:
      • app.wxss或页面的wxss中使用了标签名选择器(或一些其他特殊选择器)来直接指定样式,这些选择器会影响到页面和全部组件;通常不推荐;
      • 指定特殊的样式隔离选项styleIsolation
        • isolated: 表示启用样式隔离,使用class指定的样式将不会相互影响(一般情况下的默认值)
        • apply-shared: 表示页面wxss样式将影响到自定义组件,但自定义组件wxss中指定的样式不会影响页面;
        • shared: 表示页面wxss样式将影响到自定义组件,自定义组件wxss中指定的样式也会影响页面和其他设置了apply-shared或shared 的自定义组件(这个选项在插件中不可用;)
      • 如果这个Component构造器用于构造页面,默认值为shared;且还有额外的隔离选项可用:
        • page-isolated: 表示在这个页面禁用app.wxss,同时页面的wxss不会影响到其他自定义组件;
        • page-apply-shared: 表示在这个页面禁用app.wxss,同时页面的wxss不会影响到其他自定义组件,但设为shared的自定义组件会影响到页面;
        • page-shared: 表示在这个页面禁用app.wxss,同时页面wxss样式会影响到其他设为apply-shared 或 shared 的自定义组件,也会受到设为shared的自定义组件的影响;
    • 在2.10.1开始,也可以在页面或自定义组件的json文件配置 styleIsolation(这样不需在js中的options中再配置)
    • 在2.2.3以上,支持addGlobalClass选项,即在Component的options中设置 addGlobalClass:true; 这个选项等价于设置styleIsolation:apply-shared,但设置了styleIsolation选项后这个选项会失效;
  • 除此之外,组件可以指定它所在节点的默认样式,使用:host选择器
  • 外部样式类,可在component 中用externalClasses定义段定义若干个外部样式类; 避免同一个节点上使用普通样式类和外部样式类;
  • 即时启动了样式隔离isolated,组件仍然可以在局部引用组件所在页面的样式或父组件的样式; 可以使用~引用所在页面的样式; 可以使用^引用父组件的样式; 如果组件是比较独立通用的组件,优先使用外部样式类的方式;

在组件模板中可以提供一个 节点,用于承载组件引用时提供的子节点。 默认情况下,一个组件wxml中只能有一个slot,需要使用多slot时,可以在组件js中声明启用;


	
	
	  
	  这里是组件的内部节点
	  
	
	

	
	组件的属性 propA 和 propB 将收到页面传递的数据。页面可以通过 setData 来改变绑定的数据字段
	
	  
		这里是插入到组件slot name="before"中的内容
	    
	    这里是插入到组件slot name="after"中的内容
	  
	
	
	//引用外部样式:
	/* 组件 custom-component.js */
	Component({
		externalClasses: ['my-class']
	})

	
	这段文本的颜色由组件外的 class 决定

	
	
	
	
	

在自定义组件的js文件中,需要使用component来注册组件,并提供组件的属性定义,内部数据和自定义方法;


	Component({
	  options:{
		multipleSlots:true, // 在组件定义时的选项中启用多slot支持
		styleIsolation:'isolated'
	  }
	  properties: {
	    // 这里定义了innerText属性,属性值可以在组件使用时指定
	    innerText: {
	      type: String,
	      value: 'default value',
	    }
	  },
	  data: {
	    // 这里是一些组件内部数据
	    someData: {}
	  },
	  methods: {
	    // 这里是一个自定义方法
	    customMethod: function(){}
	  }
	})

使用自定义组件,首先在页面的json文件中进行引用声明;

  • 需要提供每个自定义组件的标签名和对应的自定义组件文件路径;
  • 引用声明后,就可以在wxml中使用基础组件一样使用自定义组件;节点名即自定义组件的标签名,节点属性即传递给组件的属性值;

	{
	  "usingComponents": {
	    "component-tag-name": "path/to/the/custom/component"
	  }
	}

tips:

  • 因为 WXML 节点标签名只能是小写字母、中划线和下划线的组合,所以自定义组件的标签名也只能包含这些字符。
  • 自定义组件也是可以引用自定义组件的,引用方法类似于页面引用自定义组件的方式(使用 usingComponents 字段)。
  • 自定义组件和页面所在项目根目录名不能以“wx-”为前缀,否则会报错。
  • 是否在页面文件中使用 usingComponents 会使得页面的 this 对象的原型稍有差异
    • 使用 usingComponents 页面的原型与不使用时不一致,即 Object.getPrototypeOf(this) 结果不同。
    • 使用 usingComponents 时会多一些方法,如 selectComponent 。
    • 出于性能考虑,使用 usingComponents 时, setData 内容不会被直接深复制,即 this.setData({ field: obj }) 后 this.data.field === obj 。(深复制会在这个值被组件间传递时发生。)

Component 构造器

Component 构造器可用于定义组件,调用Component构造器可以指定组件的属性,数据,方法等;


	Component({
	
	  behaviors: [],
	
	  properties: {
	    myProperty: { // 属性名
	      type: String,
	      value: ''
	    },
	    myProperty2: String // 简化的定义方式
	  },
	  
	  data: {}, // 私有数据,可用于模板渲染
	
	  lifetimes: {
	    // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
	    attached: function () { },
	    moved: function () { },
	    detached: function () { },
	  },
	
	  // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
	  attached: function () { }, // 此处attached的声明会被lifetimes字段中的声明覆盖
	  ready: function() { },
	
	  pageLifetimes: {
	    // 组件所在页面的生命周期函数
	    show: function () { },
	    hide: function () { },
	    resize: function () { },
	  },
	
	  methods: {
	    onMyButtonTap: function(){
	      this.setData({
	        // 更新属性和数据的方法与更新页面数据的方法类似
	      })
	    },
	    // 内部方法建议以下划线开头
	    _myPrivateMethod: function(){
	      // 这里将 data.A[0].B 设为 'myPrivateData'
	      this.setData({
	        'A[0].B': 'myPrivateData'
	      })
	    },
	    _propertyChange: function(newVal, oldVal) {
	
	    }
	  }
	
	})

使用Component构造器构造页面 ,代替 Page,需要在json中包含usingComponents定义段; 使用Component构造器来构造页面的一个好处是可以使用behaviors提取所有页面中公用的代码段; 可以在所有页面被创建和销毁时都会执行同一段代码,可以提取到behaviors;

注意: behavior 如果有同名的属性或方法,组件本身的属性或方法会覆盖behavior中的属性或方法;多个behavior,靠后的覆盖前的; 同名的数据字段如果是对象进行合并,非对象互相覆盖; 生命周期函数不会相互覆盖,而是在对应触发事件被逐个调用; 同一个behavior被一个组件多次引用,定义的生命周期函数只会被执行一次;


	{
	  "usingComponents": {}
	}

	// page-common-behavior.js
	module.exports = Behavior({
	  attached: function() {
	    // 页面创建时执行
	    console.info('Page loaded!')
	  },
	  detached: function() {
	    // 页面销毁时执行
	    console.info('Page unloaded!')
	  }
	})

	// 页面 A
	var pageCommonBehavior = require('./page-common-behavior')
	Component({
	  behaviors: [pageCommonBehavior],
	  data: { /* ... */ },
	  methods: { /* ... */ },
	})

触发事件: triggerEvent方法,指定事件名,detail对象和事件选项; 支持冒泡和捕获处理:

  • bubbles: Boolean 事件是否冒泡;
  • composed:Boolean 事件是否可以穿越组件边界,为false时,事件将只能在引用组件的节点树上触发,不进入其他任何组件内部;true ,可以进入组件内部事件;
  • capturePhase:Boolean 事件是否拥有捕获阶段;

内置behavior

  • wx://form-field : 类似于表单控件的行为;
  • wx://form-field-group : 使 form 组件可以识别到这个自定义组件内部的所有表单控件。
  • wx://component-export : 使自定义组件支持 export 定义段。这个定义段可以用于指定组件被 selectComponent 调用时的返回值。

	Component({
	  behaviors: ['wx://form-field']
	})

组件间关系

关联 relations 包含目标组件路径及其对应选项;

  • type : String 目标组件的相对关系,必填,可选值:parent/child/ancestor/descendant;
  • linked:Function 关系生命周期函数,当关系被建立在页面节点树中时触发,触发时机在组件attached生命周期之后
  • linkChanged:Function 关系生命周期函数,当关系在页面节点树中发生改变时触发,触发时机在组件moved生命周期之后
  • unlinked:Function 关系生命周期函数,当关系脱离页面节点树时触发,触发时机在组件detached生命周期之后
  • target:String 如果这一项被设置,则它表示关联的目标节点所应具有的behavior,所有拥有这一behavior的组件节点都会被关联

数据监听器 observers

**通配符 表示监听所有子数据字段的变化; 如’some.field.**'监听前缀;

纯数据字段

纯数据字段是一些不用于界面渲染的 data 字段,可以用于提升页面更新性能。 wxml不会渲染;

Component构造器的options定义段中指定pureDataPattern为一个正则表达式;字段名符合这个正则则成为纯数据字段;


	Component({
	  options: {
	    pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
	  },
	  data: {
	    a: true, // 普通数据字段
	    _b: true, // 纯数据字段
	  },
	  methods: {
	    myMethod() {
	      this.data._b // 纯数据字段可以在 this.data 中获取
	      this.setData({
	        c: true, // 普通数据字段
	        _d: true, // 纯数据字段
	      })
	    }
	  }
	})

	 这行会被展示 
	 这行不会被展示 

抽象节点

自定义组件模板中的一些节点,对应的自定义组件不是由自定义组件本身确定的,而是自定义组件的调用者确定的;


	
	
	  
	

	“selectable”不是任何在 json 文件的 usingComponents 字段中声明的组件,而是一个抽象节点。它需要在 componentGenerics 字段中声明:
	{
	  "componentGenerics": {
	    "selectable": true
	  }
	}

	  指定抽象节点为custom-radio; (也需要注册在Components)  `generic:xxx="yyy"`值只能是静态值,不能包含数据绑定;抽象节点不适用于动态决定节点名的场景;

	{
	  "usingComponents": {
	    "custom-radio": "path/to/custom/radio"
	  }
	}

自定义组件扩展

definitionFilter 提供修改自定义组件定义段的能力,用于支持自定义组件扩展; definitionFilter是一个函数,是被调用时会被注入两个参数,第一个参数是使用该behavior的component/behavior的定义对象;第二个参数是该behavior所使用的behavior的definitionFilter函数列表;

自定义组件扩展详情

你可能感兴趣的:(小程序学习)