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

小程序相关整理

小程序简介

小程序的逻辑层和渲染层是分开的,逻辑层运行在 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

  • 页面配置 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]
	  }
	})

	<!--wxml-->
	<!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
	<wxs module="m1">
	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;
	</wxs>
	
	<!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array -->
	<view> {{m1.getMax(array)}} </view>

###JS 脚本逻辑文件 javascript

用于和用户交互;


小程序宿主环境

小程序宿主环境

小程序的运行环境可分为 渲染层(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用来让更多的页面有相同的数据字段和方法;

在这里插入图片描述

微信官方文档 behaviors

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

在这里插入图片描述

小程序页面生命周期

###页面路由

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

路由方式页面栈表现触发时机路由前页面路由后页面
初始化新页面入栈小程序打开的第一个页面onLoad, onShow
打开新页面新页面入栈调用 API wx.navigateTo 使用组件 <navigator open-type="navigateTo"/>onHideonLoad, onShow
页面重定向当前页面出栈,新页面入栈调用 API wx.redirectTo 使用组件 <navigator open-type="redirectTo"/>onUnloadonLoad, onShow
页面返回页面不断出栈,直到目标返回页调用 API wx.navigateBack 使用组件<navigator open-type="navigateBack">用户按左上角返回按钮onUnloadonShow
Tab切换页面全部出栈,只留下新的tab页面调用 API wx.switchTab 使用组件 <navigator open-type="switchTab"/> 用户切换 Tab各种情况请参考下表
重加载页面全部出栈,只留下新的页面调用 API wx.reLaunch 使用组件 <navigator open-type="reLaunch"/>onUnloadonLoad, 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)
	  }
	})

	<!-- callback 形式调用 -->
	wx.chooseImage({
	  success(res) {

	    console.log('res:', res)
	  }
	})
	
	<!-- promise 形式调用 -->
	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的函数。

	--------
	<wxs module="wxs" src="./test.wxs"></wxs>
	<view id="tapTest" data-hi="WeChat" bindtap="{{wxs.tapName}}"> Click me! </view>
	**注:绑定的WXS函数必须用{{}}括起来**
	
	--------

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

	//`change:prop`是在prop属性被设置的时候触发wxs函数;
	<wxs module="test" src="./test.wxs"></wxs>
	<view change:prop="{{test.propObserver}}" prop="{{propValue}}" bindtouchmove="{{test.touchmove}}" class="movable"></view>
	
	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会响应;
	<view id="outer" bindtap="handleTap1">
	  outer view
	  <view id="middle" catchtap="handleTap2">
	    middle view
	    <view id="inner" bindtap="handleTap3">
	      inner view
	    </view>
	  </view>
	</view>

	//互斥事件,点击内部 handleTap3和handleTap2会响应;点击middle,响应handTap2和handTap1;
	<view id="outer" mut-bind:tap="handleTap1">
	  outer view
	  <view id="middle" bindtap="handleTap2">
	    middle view
	    <view id="inner" mut-bind:tap="handleTap3">
	      inner view
	    </view>
	  </view>
	</view>

	//捕获事件,点击内部 hand2 -> hand4 -> hand3 ->hand1
	<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
	  outer view
	  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
	    inner view
	  </view>
	</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不会做连字符和大小写转换;

	<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
	
	Page({
	  bindViewTap:function(event){
	    event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
	    event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
	  }
	})

	---------

	<view mark:myMark="last" bindtap="bindViewTap">
	  <button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
	</view>
		
	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,组件仍然可以在局部引用组件所在页面的样式或父组件的样式; 可以使用~引用所在页面的样式; 可以使用^引用父组件的样式; 如果组件是比较独立通用的组件,优先使用外部样式类的方式;

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


	<!-- 组件模板 -->
	<view class="wrapper">
	  <slot name="before"></slot>
	  <view>这里是组件的内部节点</view>
	  <slot name="after"></slot>
	</view>
	

	<!-- 引用组件的页面模板 -->
	组件的属性 propA 和 propB 将收到页面传递的数据。页面可以通过 setData 来改变绑定的数据字段
	<view>
	  <component-tag-name prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
		<view slot="before">这里是插入到组件slot name="before"中的内容</view>
	    <!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
	    <view slot="after">这里是插入到组件slot name="after"中的内容</view>
	  </component-tag-name>
	</view>
	
	//引用外部样式:
	/* 组件 custom-component.js */
	Component({
		externalClasses: ['my-class']
	})

	<!-- 组件 custom-component.wxml -->
	<custom-component class="my-class">这段文本的颜色由组件外的 class 决定</custom-component>

	<!-- 页面的 WXML 使用my-class的样式-->
	<custom-component my-class="red-text" />
	<custom-component my-class="large-text" />
	<!-- 以下写法需要基础库版本 2.7.1 以上 -->
	<custom-component my-class="red-text large-text" />

在自定义组件的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, // 纯数据字段
	      })
	    }
	  }
	})

	<view wx:if="{{a}}"> 这行会被展示 </view>
	<view wx:if="{{_b}}"> 这行不会被展示 </view>

抽象节点

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


	<!-- selectable-group.wxml -->
	<view wx:for="{{labels}}">
	  <label>
	    <selectable disabled="{{false}}"></selectable>
	    {{item}}
	  </label>
	</view>

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

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

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

自定义组件扩展

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

自定义组件扩展详情

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 为了回答这个问题,需要先了解wxappunpacker和wuwxss.js的作用。 wxappunpacker是一个工具,用于解析和提取微信小程序(WXAPP)的源代码文件。它可以将WXAPP的源代码解析并提取出其的各个部分,便于进一步分析和修改。 而wuwxss.js是wxappunpacker一个JavaScript文件,它主要用于解析WXAPP的.wxss文件(微信小程序样式文件)并提取其的样式规则。其的规则将被转换为JSON对象并存储在一个数组。 如果要修改wxappunpacker的wuwxss.js,可能是希望改变提取.wxss文件的样式规则的方式或者改变规则存储的方式。具体的修改可根据个人需求而定。 一种可能的修改是改变样式规则的转换方式,例如可以将.wxss文件的样式规则转换为CSS样式规则的格式。这样有助于在解析后的样式规则更方便地进行查找和修改。另外,也可以增加额外的功能,例如对样式规则进行排序、去重或者其他操作。 另一种可能的修改是改变规则存储的方式,例如可以将解析后的样式规则保存在一个对象,以便更方便地进行操作和管理。可以根据自己的需求,对对象存储的样式规则进行整理和优化。 总而言之,修改wxappunpacker的wuwxss.js可以根据实际需求,改变样式规则的转换方式或规则的存储方式,以提高对WXAPP样式文件的解析和修改效率。 ### 回答2: 修改wxappunpacker的wuwxss.js可以根据具体需求做一些相应的调整和改动。具体的修改内容可能包括以下几个方面: 1. 解析wxss文件:可以对解析的wxss文件进行添加、删除、修改等操作,以满足特定的需求。比如,可以根据项目需求添加一些额外的样式规则,或者修改原有的样式规则。 2. 文件路径处理:可以对引用的文件路径进行修改。wxappunpacker的wuwxss.js会解析wxss文件引用的图片、字体等资源路径,可以通过修改路径的方式来实现资源的替换或者修改。 3. 样式压缩和优化:可以对解析出来的样式进行压缩和优化,以减小文件大小和提高加载速度。可以通过去除空格、换行符等方式来减小文件体积,也可以对样式进行合并和同名替换,以减少样式的冗余和重复。 4. 其他功能扩展:可以根据具体需求添加其他功能,比如添加自定义的样式规则解析,支持特定的样式预处理语言等。 需要注意的是,在对wuwxss.js进行修改时,要保证修改后的代码符合原有的代码逻辑并且能够正常运行,在修改过程要注意对代码进行测试和调试,确保修改后的代码能够正常工作。 ### 回答3: 要修改wxappunpacker的wuwxss.js,首先需要理解这个文件的功能和作用。wuwxss.js主要是用来解析和处理微信小程序的wxss文件,将其转化为可读的CSS文件。 在对wuwxss.js进行修改之前,需要先确定修改的目的和需求。如果要修改或添加新的功能,需要仔细研究和了解wuwxss.js的代码结构和实现方法。可以使用文本编辑器或者开发工具打开这个文件,进行查看和修改。 在进行修改时,需要注意以下几点: 1. 修改前要备份原有的wuwxss.js文件,以防修改出错或需要恢复。 2. 了解代码的各种变量、函数和方法的含义和作用,确保修改不会影响原有的功能和逻辑。 3. 修改时要注意语法规范,确保修改的代码与整个文件的风格和格式一致。 4. 如果要添加新的功能,要考虑如何将新的代码与原有的代码结合起来,并测试确保新功能的正确性和有效性。 5. 修改完成后要经过测试和验证,确保修改后的wuwxss.js仍然可以正常工作,并且没有引入新的bug或错误。 最后,修改wuwxss.js并不是一件简单的事情,需要有一定的前端开发经验和技术能力。如果遇到困难或疑问,可以参考相关文档、教程或寻求其他开发者的帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值