Weapy笔记

官方文档

快速入门

安装

npm install wepy-cli -g

生成工程

wepy new myproject

进入工程目录

cd myproject

实时编译项目

wepy build --watch

注意事项:

  1. 使用微信开发者工具新建项目,本地开发选择dist目录。
  2. 微信开发者工具-->项目-->关闭ES6转ES5。重要:漏掉此项会运行报错。
  3. 微信开发者工具-->项目-->关闭上传代码时样式自动补全 重要:某些情况下漏掉此项会也会运行报错。
  4. 微信开发者工具-->项目-->关闭代码压缩上传 重要:开启后,会导致真机computed, props.sync 等等属性失效。
  5. 本地项目根目录运行wepy build --watch,开启实时编译。

代码规范:

  1. 变量与方法使用尽量使用驼峰式命名,避免使用$
    开头。 以$
    开头的方法或者属性为框架内建方法或者属性,可以被使用,使用前请参考API文档。
  2. 入口,页面,组件的命名后缀为.wpy
    。外链的文件可以是其它后缀。 请参考wpy文件说明
  3. 使用ES6语法开发。 框架在ES6下开发,因此也需要使用ES6开发小程序,ES6中有大量的语法糖可以让我们的代码更加简洁高效。
  4. 使用Promise: 框架默认对小程序提供的API全都进行了 Promise 处理,甚至可以直接使用async/await等新特性进行开发。
  5. 事件绑定语法使用优化语法代替: 原bindtap="click"替换为@tap="click",原catchtap="click"替换为@tap.stop="click"。更多@
    符用法,参见组件自定义事件。
    事件传参使用优化后语法代替: 原bindtap="click" data-index={{index}}替换为@tap="click({{index}})"。
  6. 自定义组件命名应避开微信原生组件以及功能标签。 不可以使用input, button, view, repeat等命名自定义组件。更多repeat用法,参见循环列表组件引用。

笔记

1. 组件

组件页面入口继承自wepy.component,属性与页面属性一样,除了不需要config以及页面特有的一些小程序事件等等。

2. 实例

小程序在 WePY 中,被分为三个实例,App,Page,Component。其中Page实例继承自Component。声明方式如下:

import wepy from 'wepy';

// 声明一个App文件
export default class MyAPP extends wepy.app {
}
// 声明一个Page文件
export default class IndexPage extends wepy.page {
}
// 声明一个组件文件
export default class MyComponent extends wepy.component {
}
  • App 实例中只包含小程序生命周期函数以及自定义方法与属性
import wepy from 'wepy';

export default class MyAPP extends wepy.app {
    customData = {};

    customFunction () { }

    onLaunch () {}

    onShow () {}

    config = {}; // 对应 app.json 文件
}

在 Page 实例中,可以通过this.$parent来访问 App 实例。

  • Page 和 Component 实例
    Page 实例中只包含小程序页面生命周期函数,自定义方法与属性以及特有属性。
import wepy from 'wepy';

// export default class MyPage extends wepy.page {
export default class MyPage extends wepy.component {
    customData = {};

    customFunction () {}

    onLoad () {} // 只在 Page 实例中会存在页面生命周期函数

    onShow () {} // 只在 Page 实例中会存在页面生命周期函数

    // 特有属性示例

    config = {}; // 对应page.json文件,只在 Page 实例中存在

    data = {}; // 页面所需数据均需在这里声明

    components = {}; // 声明页面所引用的子组件

    mixins = []; // 声明页面所引用的Mixin实例

    computed = {}; // 声明[计算属性](https://wepyjs.github.io/wepy/#/?id=computed-%e8%ae%a1%e7%ae%97%e5%b1%9e%e6%80%a7)

    watch = {}; // 声明数据watcher

    methods = {}; // 声明页面响应事件。注意,此处只用于声明页面bind,catch事件,自定义方法需以自定义方法的方式声明

    events = {}; // 声明组件之间的事件传递
}

对于 methods 属性,因为与Vue的使用习惯不一致,一直存在一个误区,这里的 methods 属性只声明页面bind,catch事件,不能声明自定义方法

3. 普通组件引用

当页面或者组件需要引入子组件时,需要在页面或者script中的components给组件分配唯一id,并且在template中添加标签。
WePY中的组件都是静态组件,是以组件ID作为唯一标识的,每一个ID都对应一个组件实例,当页面引入两个相同ID组件时,这两个组件共用同一个实例与数据,当其中一个组件数据变化时,另外一个也会一起变化。 如果需要避免这个问题,则需要分配多个组件ID和实例

4. 循环列表组件引用

1.4.6新增
当想在wx:for中使用组件时,需要使用辅助标签

5.computed 计算属性

  • 类型: { [key: string]: Function }

  • 详细: 计算属性可以直接当作绑定数据,在每次脏检查周期中。在每次脏检查流程中,只要有脏数据,那么computed 属性就会重新计算。

data = {
      a: 1
  };

  computed = {
      aPlus () {
          return this.a + 1;
      }
  }

6. watcher

  • 类型: { [key: string]: Function }
  • 详细: 通过watcher我们能监听到任何数值属性的数值更新。
  data = {
      num: 1
  };

  watch = {
      num (newValue, oldValue) {
          console.log(`num value: ${oldValue} -> ${newValue}`)
      }
  }

  onLoad () {
      setInterval(() => {
          this.num++;
          this.$apply();
      }, 1000)
  }

7. Props传值

静态传值

使用静态传值时,子组件会接收到字符串的值。

// parent.wpy


data = {
    parentTitle: 'p-title'
};


// child.wpy
props = {
    title: String,
    syncTitle: {
        type: String,
        default: 'null'
    },
    twoWayTitle: {
        type: Number,
        default: 50,
        twoWay: true
    }
};

onLoad () {
    console.log(this.title); // p-title
    console.log(this.syncTitle); // p-title
    console.log(this.twoWayTitle); // 50

    this.title = 'c-title';
    console.log(this.$parent.parentTitle); // p-title.
    this.twoWayTitle = 60;
    console.log(this.$parent.parentTitle); // 60.  --- twoWay为true时,子组件props修改会改变父组件对应的值
    this.$parent.parentTitle = 'p-title-changed';
    console.log(this.title); // 'p-title';
    console.log(this.syncTitle); // 'p-title-changed' --- 有sync属性的props,当父组件改变时,会影响子组件的值。
}

组件通信与交互

wepy.component基类提供三个方法$broadcast$emit$invoke,因此任一页面或任一组件都可以调用上述三种方法实现通信与交互,如

this.$emit('some-event', 1, 2, 3, 4);

组件的事件监听需要写在events属性下,如:

import wepy from 'wepy';
export default class Com extends wepy.component {

    components = {};

    data = {};
    methods = {};

    events = {
        'some-event': (p1, p2, p3, $event) => {
               console.log(`${this.name} receive ${$event.name} from ${$event.source.name}`);
        }
    };
    // Other properties
}
  • $broadcast
    broadcast事件是由父组件发起,所有子组件都会收到此广播事件,除非事件被手动取消。事件广播的顺序为广度优先搜索顺序
  • $emit

$emit$broadcast正好相反,事件发起组件的父组件会依次接收到$emit事件,如上图,如果E发起一个$emit事件,那么接收到事件的先后顺序为:A, Page_Index。

  • $invoke

$invoke是一个组件对另一个组件的直接调用,通过传入的组件路径找到相应组件,然后再调用其方法。 如果想在Page_Index中调用组件A的某个方法:

this.$invoke('ComA', 'someMethod', 'someArgs');

如果想在组件A中调用组件G的某个方法:

this.$invoke('./../ComB/ComG', 'someMethod', 'someArgs');

组件自定义事件

1.4.8新增
可以使用@customEvent.user绑定用户自定义组件事件。其中,@表示事件修饰符,customEvent表示事件名称,.user表示事件后缀。
目前有三种后缀:

  • .default: 绑定小程序冒泡事件事件,如bindtap。

  • .stop: 绑定小程序非冒泡事件,如catchtap。

  • .user: 绑定用户自定义组件事件,通过$emit触发。

拦截器

可以使用全域拦截器配置API的config、fail、success、complete方法,参考示例:

import wepy from 'wepy';

export default class extends wepy.app {

    constructor () {
        this.intercept('request', {
            config (p) {
                p.timestamp = +new Date();
                return p;
            },
            success (p) {
                console.log('request success');
                return p;
            },
            fail (p) {
                console.log('request error');
                return p;
            }
        });
    }
}

数据绑定

小程序数据绑定方式

小程序通过Page提供的setData方法去绑定数据,如:this.setData({title: 'this is title'});因为小程序架构本身原因,页面渲染层和JS逻辑层分开的,setData操作实际就是JS逻辑层与页面渲染层之间的通信,那么如果在同一次运行周期内多次执行setData操作时,那么通信的次数是一次还是多次呢?这个取决于API本身的设计。

wepy数据绑定方式

wepy使用脏数据检查对setData进行封装,在函数运行周期结束时执行脏数据检查,一来可以不用关心页面多次setData是否会有性能上的问题,二来可以更加简洁去修改数据实现绑定,不用重复去写setData方法。代码如下:

this.title = 'this is title';

但需注意,在函数运行周期之外的函数里去修改数据需要手动调用$apply
方法。如:

setTimeout(() => {
   this.title = 'this is title'; 
   this.$apply();
}, 3000);

App方法

  • use(middleWare:String|Function):使用中间件。
    当前内置两个中间件:

requestfix: 修复小程序请求并发问题。
promisify:使用wepy.xxx的方式请求小程序原生API都将Promise化。

使用方法如下:

this.use('requestfix');
this.use('promisify');
  • intercept(api:String, provider:Object):使用拦截器对原生API请求进行拦截。

格式如下:

  // app.js
  constructor () {
      super();
      this.intercept('request', {
          config (p) {
              p.timestamp = +new Date();
          },
          success (obj) {
              console.log('request success');
          }
      });
  }

wepy.component Class

组件基类

属性

  • $name:String: 组件名称。
  • $isComponent:Boolean:是否是组件,如果是页面,此值为false。
  • $wxpage:Object: 小程序原生page。
  • $parent:Page|App:组件的父组件,如果当前是组件是Page对象,那么$parent的值为App对象。
  • $root:Page: 组件所在的Page对象,如果当前组件是Page对象,那么$root的值就是自己本身。
  • $coms:List:组件的子组件列表。
  • $mixins:Array[Mixin]:组件所注入的Mixin对象。
  • data:Object: 组件需要绑定的数据。
  • methods:List:组件需要响应的事件列表。
  • props:List:组件允许传递的props列表。
  • events:List:组件通信时所需要的事件表现。

方法

  • setData(key:String|Object, [value:Object]):对原有小程序的setData的封装。

因为WePY的脏查检流程会自动执行setData操作,所以通常情况下不需要使用此方法。

  • getCurrentPages():相当于全局方法getCurrentPages()。

  • $getComponent(com:String):通过组件名称路径查找组件对象。

  • $broadcast(eventName:String, [args]):组件发起一个广播事件。

向所有子组件发起一个广播事件,事件会依次传播直至所有子组件遍历完毕或者事件被手动终止传播。

  • $emit(eventName:String, [args]):组件发起一个冒泡事件。

向父组件发起一个冒泡事件,事件会向上冒泡直至Page或者者事件被手动终止传播。

  • $apply([func:Function]):组件发起脏检查。

正常流程下,改变数据后,组件会在流程结束时自动触发脏检查。 在异步或者回调流程中改变数据时,需要手动调用$apply方法。

wepy.page Class

页面类,继承自wepy.component,拥有页面所有的属性与方法。
属性
全部属性继承自wepy.component。
方法

  • $preload(key:String|Object, [value:Object]):给页面加载preload数据
    加载preload数据后,跳转至另一个页面时,在onLoad方法中可以获取到上个页面的preload数据。
    使用方法如下:
// page1.js this.$preload('userName': 'Gcaufy'); this.$redirect('./page2'); // page2.js onLoad (params, data) { console.log(data.preload.userName); }
  • $redirect(url:String|Object, [params:Object]):wx.redirectTo的封装方法。
    使用方法如下:
this.$redirect('./page2', {a: 1, b: 2}); this.$redirect({ url: './pages?a=1&b=2' });
  • $navigate(url:String|Object, [params:Object]):wx.navigateTo的封装方法

  • $switch(url:String|Object):wx.switchTab的封装方法

预加载

请求数据是在onLoad中进行,但是小程序的 page 1跳转到 page 2,再到 page 2 的 onLoad是存在一个 300ms ~ 400ms 的延时.
wepy扩展了生命周期,添加了onPrefetch事件,会在 redirect之时被主动调用。同时给onLoad事件添加了一个参数,用于接收预加载或者是预查询的数据:

// params
// data.from: 来源页面,page1
// data.prefetch: 预查询数据
// data.preload: 预加载数据
onLoad (params, data) {}

预加载数据示例:

// page1.wpy 预先加载 page2 需要的数据。

methods: {
  tap () {
    this.$redirect('./page2');
  }
},
onLoad () {
  setTimeout(() => {
    this.$preload('list', api.getBigList())
  }, 3000)
}

// page2.wpy 直接从参数中拿到 page1 中预先加载的数据
onLoad (params, data) {
  data.preload.list.then((list) => render(list));
}

预查询数据示例:

// page1.wpy 使用封装的 redirect 方法跳转时,会调用 page2 的 onPrefetch 方法
methods: {
  tap () {
    this.$redirect('./page2');
  }
}

// page2.wpy 直接从参数中拿到 onPrefetch 中返回的数据
onPrefetch () {
  return api.getBigList();
}
onLoad (params, data) {
  data.prefetch.then((list) => render(list));
}

参考

你可能感兴趣的:(Weapy笔记)