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. 自定义组件命名应避开微信原生组件以及功能标签<repeat>。 不可以使用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中添加<component>标签。
WePY中的组件都是静态组件,是以组件ID作为唯一标识的,每一个ID都对应一个组件实例,当页面引入两个相同ID组件时,这两个组件共用同一个实例与数据,当其中一个组件数据变化时,另外一个也会一起变化。 如果需要避免这个问题,则需要分配多个组件ID和实例

4. 循环列表组件引用

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

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
<child :title="parentTitle" :syncTitle.sync="parentTitle" :twoWayTitle="parentTitle"></child>

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<Component>:组件的子组件列表。
  • $mixins:Array[Mixin]:组件所注入的Mixin对象。
  • data:Object: 组件需要绑定的数据。
  • methods:List<Function>:组件需要响应的事件列表。
  • props:List<Props>:组件允许传递的props列表。
  • events:List<Function>:组件通信时所需要的事件表现。

方法

  • 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));
}

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,621评论 18 399
  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,048评论 0 29
  • 一. Java基础部分.................................................
    wy_sure阅读 3,810评论 0 11
  • 一楼一灯一具琴,几回寒暑,任它春秋,只待花满江楼,幽花化清茶,再唤一声,花满楼。 隐江南小楼,花开卷云袖。 花满楼...
    柠鹿阅读 1,344评论 0 13