wepy_wepy build 报错 - CSDN
精华内容
参与话题
  • 使用 wepy 开发的小程序Demo
  • wepy快速入门

    千次阅读 2019-05-13 10:12:01
    Github地址 wepy官网:https://tencent.github.io/wepy/index.html 安装 wepy 命令行工具 npm install wepy-cli -g 在开发目录生成开发DEMO ...npm install -g wepy-cli //全局安装或更新WePY命令行工...

    Github地址

    wepy官网:https://tencent.github.io/wepy/index.html

    安装 wepy 命令行工具

    npm install wepy-cli -g
    

    在开发目录生成开发DEMO

    wepy new myproject
    

    开发实时编译

    wepy build --watch
    
    npm install -g wepy-cli  //全局安装或更新WePY命令行工具(wepy脚手架): wepy-cli
    wepy -v //查看wepy-cli版本
    wepy init standard <projectName> //新建wepy小程序项目,1.7.0之前的版本使用:wepy new myproject
    wepy list //查看项目模板
    cd <projectName> //切换至项目目录
    npm  install //安装依赖
    wepy build --watch //开启实时编译
    

    在这里插入图片描述
    WePY项目的目录结构

    ├── dist                   小程序运行代码目录(该目录由WePY的build指令自动编译生成,请不要直接修改该目录下的文件)
    ├── node_modules           
    ├── src                    代码编写的目录(该目录为使用WePY后的开发目录)
    |   ├── components         WePY组件目录(组件不属于完整页面,仅供完整页面或其他组件引用)
    |   |   ├── com_a.wpy      可复用的WePY组件a
    |   |   └── com_b.wpy      可复用的WePY组件b
    |   ├── pages              WePY页面目录(属于完整页面)
    |   |   ├── index.wpy      index页面(经build后,会在dist目录下的pages目录生成index.js、index.json、index.wxml和index.wxss文件)
    |   |   └── other.wpy      other页面(经build后,会在dist目录下的pages目录生成other.js、other.json、other.wxml和other.wxss文件)
    |   └── app.wpy            小程序配置项(全局数据、样式、声明钩子等;经build后,会在dist目录下生成app.js、app.json和app.wxss文件)
    └── package.json           项目的package配置
    

    在这里插入图片描述

    project.config.json文件内容如下:

    {
      "description": "project description",
      "setting": {
        "urlCheck": true,
        "es6": false,
        "postcss": false,
        "minified": false
      },
      "compileType": "miniprogram",
      "appid": "touristappid",
      "projectname": "Project name",
      "miniprogramRoot": "./dist"
    }
    

    es6: 对应关闭ES6转ES5选项,关闭。 重要:未关闭会运行报错。

    postcss: 对应关闭上传代码时样式自动补全选项,关闭。 重要:某些情况下漏掉此项也会运行报错。

    minified: 对应关闭代码压缩上传选项,关闭。重要:开启后,会导致真机computed, props.sync 等等属性失效。

    urlCheck: 对应不检查安全域名选项,开启。 如果已配置好安全域名则建议关闭。

    展开全文
  • 快速入门 WePY 小程序

    2018-10-24 15:37:04
    一、WePY介绍 WePY 是 腾讯 参考了Vue 等框架对原生小程序进行再次封装的框架,更贴近于 MVVM 架构模式, 并支持ES6/7的一些新特性。 二、WePY 使用 1、WePY的安装或更新都通过npm进行: npm install -g wepy-...

    一、WePY介绍

    WePY 是 腾讯 参考了Vue 等框架对原生小程序进行再次封装的框架,更贴近于 MVVM 架构模式, 并支持ES6/7的一些新特性。

    二、WePY 使用

    1、WePY的安装或更新都通过npm进行:

    npm install -g wepy-cli  //全局安装或更新WePY命令行工具(wepy脚手架): wepy-cli
    wepy -v //查看wepy-cli版本
    wepy init standard <projectName> //新建wepy小程序项目,1.7.0之前的版本使用:wepy new myproject
    wepy list //查看项目模板
    cd <projectName> //切换至项目目录
    npm  install //安装依赖
    wepy build --watch //开启实时编译

    git base here:

    (1)全局安装或更新 wepy-cli:

    (2)查看 wepy-cli 版本:

    (3)创建 wepy 小程序项目:

    (4)切换至项目目录,安装依赖:

    (5)开启实时编译

    2、代码高亮WebStorm/PhpStorm(其他工具参见wepy官网代码高亮

    (1)打开Settings,搜索Plugins,搜索Vue.js插件并安装。

    (2) 打开Settings,搜索File Types,找到Vue.js Template,在Registered Patterns添加*.wpy,即可高亮。

    3、代码优化

    (1)代码规范

    • wepy标签和原生一样
    • 自定义组件命名应避开:原生组件名(input、button、view、repeat等)、WePY的辅助标签<repeat>
    • 变量/方法名尽量使用驼峰式命名,避免使用$开头($开头的标识符是WePY内建属性/方法,可在js中以this.的方式直接使用,具体请参考API文档
    • app、pages、components文件名的后缀为.wpy,外链的文件可以是其它后缀。 具体请参考wpy文件说明
    • 支持ES6/7的一些新特性,框架在ES6(ECMAScript 6)下开发(默认使用babel编译),因此也需要使用ES6开发小程序,ES6中有大量的语法糖可以让我们的代码更加简洁高效。
    • wepy继承了wx对象的方法,建议在wepy框架开发中不要用到wx对象的方法,虽然运行时效果是一样,但是打包时会cli报错(wepy中没有wx对象)wepy中组件中使用的是class,vue中使用的的是对象。

    (2)数据绑定

    小程序页面渲染层和JS逻辑层分开的,setData操作实际就是JS逻辑层与页面渲染层之间的通信,在同一次运行周期内多次执行setData操作时,通信的次数是一次还是多次取决于API本身的设计。WePY使用脏数据检查对setData进行封装,在函数运行周期结束时执行脏数据检查,一来可以不用关心页面多次setData是否会有性能上的问题,二来可以更加简洁去修改数据实现绑定,不用重复去写setData方法。

    //原生小程序
    this.setData({title: 'this is title'});//通过Page提供的setData方法来绑定数据
    
    //wepy
    this.title = 'this is title';
    
    
    //wepy 在异步函数中更新数据的时候,必须手动调用$apply方法,才会触发脏数据检查流程的运行
    setTimeout(() => {
        this.title = 'this is title';
        this.$apply();
    }, 3000)
    
    
    //保留setData方法,但不建议使用setData执行绑定,修复传入undefined的bug,并且修改入参支持: 
    this.setData(target, value) 
    this.setData(object)

    (3)事件绑定以及传参优化

    <view @tap="click"></view> //​​​​​ 原 bindtap="click"(省略了.default后缀 )绑定小程序冒泡型事件
    <view @tap.stop="click"></view> //​​​​​ 原catchtap="click"  绑定小程序捕获型事件,如catchtap
    <view @tap.capture="click"></view> //​​​​​ 原 capture-bind:tap="click"
    <view @tap.capture.stop="click"></view> //​​​​​ 原 capture-catch:tap="click"
    <!--事件传参-->
    <view @tap="click({{index}})"></view> //​​​​​ 原bindtap="click" data-index={{index}}

    (4)框架默认对小程序提供的API全都进行了 Promise 处理,甚至可以直接使用async/await等新特性进行开发,同时修复了一些原生API的缺陷(如:wx.request的并发问题等)

    // 原生代码:
    
    wx.request({
        url: 'xxx',
        success: function (data) {
            console.log(data);
        }
    });
    
    // WePY 使用方式, 需要开启 Promise 支持,参考开发规范章节
    wepy.request('xxxx').then((d) => console.log(d));
    
    // async/await 的使用方式, 需要开启 Promise 和 async/await 支持,参考 WIKI
    async function request () {
       let d = await wepy.request('xxxxx');
       console.log(d);
    }

    (5)computed 计算属性computed计算属性(类型{ [key: string]: Function }),是一个有返回值的函数,可直接被当作绑定数据来使用,类似于data属性。需要注意的是,只要是组件中有任何数据发生了改变,那么所有计算属性就都会被重新计算。

      data = {
          a: 1
      }
    
      // 计算属性aPlus,在脚本中可通过this.aPlus来引用,在模板中可通过{{ aPlus }}来插值
      computed = {
          aPlus () {
              return this.a + 1
          }
      }

    (6)watcher 监听器

    通过监听器watcher(类型{ [key: string]: Function })能够监听到任何属性的更新。监听器适用于当属性改变时需要进行某些额外处理的情形。

      data = {
          num: 1
      }
    
      // 监听器函数名必须跟需要被监听的data对象中的属性num同名,
      // 其参数中的newValue为属性改变后的新值,oldValue为改变前的旧值
      watch = {
          num (newValue, oldValue) {
              console.log(`num value: ${oldValue} -> ${newValue}`)
          }
      }
    
      // 每当被监听的属性num改变一次,对应的同名监听器函数num()就被自动调用执行一次
      onLoad () {
          setInterval(() => {
              this.num++;
              this.$apply();
          }, 1000)
      }

    (7)WXS (WeiXin Script)

    WePY 从1.7.x 版本开始支持 wxs 语法,但语法与原生 wxs 稍有出入

    ①wxs是基于原生的wxs去实现的,只是通过编译把现在的语法编译为原生语法

    ②wxs必须是外链文件。并且后缀为.wxs

    ③wxs引入后只能在template中使用,不能在script中使用

    /**
    project
    └── src
        ├── wxs
        |   └── mywxs.wxs      wxs 文件 
        ├── pages
        |   └── index.wpy      页面
        └──app.wpy           
    **/
    
    // mywxs.wxs
    
    module.exports = {
      text: 'This is from wxs',
      filter: function (num) {
        return num.toFixed(2);
      }
    };
    
    // index.wpy
    
    <template>
      <text>{{m1.text}}</text>
      <text>{{m1.filter(num)}}</text>
    </template>
    
    <script>
      import wepy from 'wepy';
      import mywxs from '../wxs/mywxs.wxs';
    
      export default class Index extends wepy.page {
    
        data = {
          num: 10
        };
    
        wxs = {
          m1: mywxs
        }
    
      };
    </script>

    (8)interceptor 拦截器

    可以使用WePY提供的全局拦截器对原生API的请求进行拦截。具体方法是配置API的config、fail、success、complete回调函数。参考示例:

    import wepy from 'wepy';
    
    export default class extends wepy.app {
        constructor () {
            // this is not allowed before super()
            super();
            // 拦截request请求
            this.intercept('request', {
                // 发出请求时的回调函数
                config (p) {
                    // 对所有request请求中的OBJECT参数对象统一附加时间戳属性
                    p.timestamp = +new Date();
                    console.log('config request: ', p);
                    // 必须返回OBJECT参数对象,否则无法发送请求到服务端
                    return p;
                },
    
                // 请求成功后的回调函数
                success (p) {
                    // 可以在这里对收到的响应数据对象进行加工处理
                    console.log('request success: ', p);
                    // 必须返回响应数据对象,否则后续无法对响应数据进行处理
                    return p;
                },
    
                //请求失败后的回调函数
                fail (p) {
                    console.log('request fail: ', p);
                    // 必须返回响应数据对象,否则后续无法对响应数据进行处理
                    return p;
                },
    
                // 请求完成时的回调函数(请求成功或失败都会被执行)
                complete (p) {
                    console.log('request complete: ', p);
                }
            });
        }
    }

    三、WePY项目的目录结构

    dist目录为WePY通过build指令生成的目录,除额外增加的npm目录外,其目录结构与原生小程序的目录结构类似。

    原生小程序:app(app.jsapp.jsonapp.wxss),page(page.jspage.jsonpage.wxmlpage.wxss),文件必须同名。WePY中则使用了单文件模式:app.wpypage.wpy

     ==> 

    一个.wpy文件可分为三大部分,各自对应于一个标签:

    1. 脚本<script>部分,又可分为两个部分:

        逻辑部分,除了config对象之外的部分,对应于原生的.js文件

        配置部分,即config对象,对应于原生的.json文件

    1. 结构<template>部分,对应于原生的.wxml文件

    2. 样式<style>部分,对应于原生的.wxss文件

    <!--lang决定了其代码编译过程,src决定是否外联代码,存在src属性且有效时,会忽略内联代码-->
    <style lang="less" src="page1.less"></style>//lang值:css(默认)、less、scss、stylus、postcss
    <template lang="wxml" src="page1.wxml"></template>//lang值:wxml(默认)、xml、pug(原jade)。入口文件app.wpy不需要template,所以编译时会被忽略。
    <script></script>//lang值:babel(默认、TypeScript

    主要对目录的以下几点分析(其他目录文件详解类似于https://my.oschina.net/wangnian/blog/2050375中做的分析):

    1、src文件夹

    (1)components组件:

    组件实例继承自wepy.component类,除了不需要config配置以及页面特有的一些生命周期函数之外,其属性与页面属性大致相同:

    import wepy from 'wepy';
    
    export default class MyComponent extends wepy.component {
        props = {}//接收父组件传来的参数
        customData = {}  // 自定义数据
        customFunction () {}  //自定义方法
        onLoad () {}  // 在Page和Component共用的生命周期函数
        data = {};  // 页面所需数据均需在这里声明,可用于模板数据绑定
        components = {};  // 声明页面中所引用的组件,或声明组件中所引用的子组件
        mixins = [];  // 声明页面所引用的Mixin实例
        computed = {};  // 声明计算属性(详见后文介绍)
        watch = {};  // 声明数据watcher(详见后文介绍)
        methods = {};  // 声明页面wxml中标签的事件处理函数。注意,此处只用于声明页面wxml中标签的bind、catch事件,自定义方法需以自定义方法的方式声明
        events = {};  // WePY组件事件处理函数对象,存放响应组件之间通过$broadcast、$emit、$invoke所传递的事件的函数
    }
    /** 与page不同的是component不存在:
        onShow () {}  // 只在Page中存在的页面生命周期函数
        config = {};  // 只在Page实例中存在的配置数据,对应于原生的page.json文件,类似于app.wpy中的config
        onReady() {}  //  只在Page中存在的页面生命周期函数
    **/

    原生小程序支持js模块化,但彼此独立,业务代码与交互事件仍需在页面处理。无法实现组件化的松耦合与复用(如,模板A中绑定一个bindtap="myclick",模板B中同样绑定一样bindtap="myclick",那么就会影响同一个页面事件、数据)

    WePY组件的所有业务与功能在组件本身实现,组件与组件之间彼此隔离(上述例子在WePY的组件化开发过程中,A组件只会影响到A所绑定的myclick,B也如此)

    // 原生代码:
    
    <!-- item.wxml -->
    <template name="item">
      <text>{{text}}</text>
    </template>
    
    <!-- index.wxml -->
    <import src="item.wxml"/>
    <template is="item" data="{{text: 'forbar'}}"/>
    
    <!-- index.js -->
    var item = require('item.js')
    
    
    
    
    // WePY
    <!-- /components/item.wpy -->
     <text>{{text}}</text>
    
    <!-- index.wpy -->
    <template>
        <com></com>
    </template>
    <script>
        import wepy from 'wepy';
        import Item from '../components/item';
        export default class Index extends wepy.page {
            components = { com: Item }
        }
    </script>

    ps,在 1.7.2-alpha4 的实验版本中提供了对原生组件的支持

    ①引用组件

    页面可以引入组件,而组件还可以引入子组件

    /**
    project
    └── src
        ├── components
        |   └── child.wpy
        ├── pages
        |   ├── index.wpy    index 页面配置、结构、样式、逻辑
        |   └── log.wpy      log 页面配置、结构、样式、逻辑
        └──app.wpy           小程序配置项(全局公共配置、公共样式、声明钩子等)
    **/
    
    // index.wpy
    
    <template>
        <!-- 以`<script>`脚本部分中所声明的组件ID为名命名自定义标签,从而在`<template>`模板部分中插入组件 -->
       <view class="child1">
            <child></child>
        </view>
    
        <view class="child2">
    <!--注意:WePY中,在父组件template模板部分插入驼峰式命名的子组件标签时,不能将驼峰式命名转换成短横杆式命名(比如将childCom转换成child-com,这与Vue中不一致)-->
            <anotherchild></anotherchild>
        </view>
    </template>
    
    <script>
        import wepy from 'wepy';
        //引入组件文件
        import Child from '../components/child';
    
        export default class Index extends wepy.component {
            //声明组件,分配组件id为child,需要注意的是,WePY中的组件都是静态组件,是以组件ID作为唯一标识的,每一个ID都对应一个组件实例,当页面引入两个相同ID的组件时,这两个组件共用同一个实例与数据,当其中一个组件数据变化时,另外一个也会一起变化。
            components = {
                //为两个相同组件的不同实例分配不同的组件ID,从而避免数据同步变化的问题
                child: Child,
                anotherchild: Child
            };
        }
    </script>

    ②循环渲染组件(1.4.6新增

    WePY 1.x 版本中,循环渲染WePY组件时(类似于通过wx:for循环渲染原生的wxml标签),必须使用WePY定义的辅助标签<repeat>

    WePY组件是静态编译组件(在编译阶段编译进页面),每个组件都是唯一的一个实例,目前只提供简单的 repeat 支持(不支持在 repeat 的组件中去使用 propscomputedwatch 等),因此如下:

    <!-- 错误使用 --->
    // list.wpy
    <view>{{test.name}}</view>
    
    // index.wpy
    <repeat for="{{mylist}}">
       <List :test.sync="item"></List>
    </repeat>
    
    <!-- 推荐用法 --->
    // list.wpy
    <repeat for="{{mylist}}">
        <view>{{item.name}}</view>
    </repeat>
    
    // index.wpy
    <List :mylist.sync="mylist"></List>

    ③props 传值

    props传值在WePY中属于父子组件之间传值的一种机制,包括静态传值与动态传值。

    静态传值为父组件向子组件传递常量数据,因此只能传递String字符串类型

    动态传值是指父组件向子组件传递动态数据内容,父子组件数据完全独立互不干扰。但可以通过使用.sync修饰符来达到父组件数据绑定至子组件的效果,也可以通过设置子组件props的twoWay: true来达到子组件数据绑定至父组件的效果。如果既使用.sync修饰符,同时子组件props中添加的twoWay: true时,就可以实现数据的双向绑定。

    // parent.wpy
    
    <!--在父组件template模板部分所插入的子组件标签中,使用:prop属性(等价于Vue中的v-bind:prop属性)来进行动态传值-->
    <child :title="parentTitle" :syncTitle.sync="parentTitle" :twoWayTitle="parentTitle"></child>
    <!--通过使用.sync修饰符来达到父组件数据绑定至子组件的效果-->
    <script>
    data = {
        parentTitle: 'p-title'
    };
    </script>
    
    // child.wpy
    
    <script>
    props = {
        // 静态传值
        title: String,
    
        // 父向子单向动态传值
        syncTitle: {
            type: String,
            default: 'null'
        },
       // 双向绑定
        twoWayTitle: {
            type: String,
            default: 'nothing',
            twoWay: true//twoWay: true(默认false)来达到子组件数据绑定至父组件的效果,如果同时使用.sync修饰符,就可以实现双向绑定
        }
    };
    
    onLoad () {
        console.log(this.title); // p-title
        console.log(this.syncTitle); // p-title
        console.log(this.twoWayTitle); // p-title
    
        this.title = 'c-title';
        console.log(this.$parent.parentTitle); // p-title.
        this.twoWayTitle = 'two-way-title';
        this.$apply();
        console.log(this.$parent.parentTitle); // two-way-title.  --- twoWay为true时,子组件props中的属性值改变时,会同时改变父组件对应的值
        this.$parent.parentTitle = 'p-title-changed';
        this.$parent.$apply();
        console.log(this.title); // 'c-title';
        console.log(this.syncTitle); // 'p-title-changed' --- 有.sync修饰符的props属性值,当在父组件中改变时,会同时改变子组件对应的值。
    }
    </script>

    ④组件通信与交互

    wepy.component基类提供$broadcast$emit$invoke三个方法用于组件之间的通信和交互:

    $broadcast

    $broadcast事件是由父组件发起,所有子组件都会收到此广播事件,除非事件被手动取消。事件广播的顺序为广度优先搜索顺序

    $emit

    $emit$broadcast正好相反,组件发起事件后所有祖先组件会依次接收到$emit事件

    //子组件:
    this.$emit('some-event', 1, 2, 3, 4);
    
    //父组件:
    import wepy from 'wepy'
    
    export default class Com extends wepy.component {
        components = {};
    
        data = {};
    
        methods = {};
    
        // events对象中所声明的函数为用于监听组件之间的通信与交互事件的事件处理函数
        events = {
            'some-event': (p1, p2, p3, $event) => {
                   console.log(`${this.$name} receive ${$event.name} from ${$event.source.$name}`);
            }
        };
        // Other properties
    }

    $invoke

    $invoke是一个页面/组件对另一个组件中的方法的直接调用,通过传入组件路径找到相应的组件,然后再调用其方法。

    this.$invoke('ComA', 'someMethod', 'someArgs');//在页面Page_Index中调用组件ComA的某个方法
    this.$invoke('./../ComB/ComG', 'someMethod', 'someArgs');//在组件ComA中调用组件ComG的某个方法

    ⑤组件自定义事件处理函数(.user事件后缀,1.4.8新增

    示例如下(注意,如果用了自定义事件,则events中对应的监听函数不会再执行):

    // index.wpy
    
    <template>
        <child @childFn.user="parentFn"></child>
    </template>
    
    <script>
        import wepy from 'wepy'
        import Child from '../components/child'
    
        export default class Index extends wepy.page {
            components = {
                child: Child
            }
    
            methods = {
                parentFn (num, evt) {
                    console.log('parent received emit event, number is: ' + num)
                }
            }
        }
    </script>
    
    
    // child.wpy
    
    <template>
        <view @tap="tap">Click me</view>
    </template>
    
    <script>
        import wepy from 'wepy'
    
        export default class Child extends wepy.component {
            methods = {
                tap () {
                    console.log('child is clicked')
                    this.$emit('childFn', 100)
                }
            }
        }
    </script>

    ⑥slot 组件内容分发插槽

    WePY中的slot插槽作为内容分发标签的空间占位标签,便于在父组件中通过对相当于扩展板卡的内容分发标签的“插拔”,更为灵活、方便地对子组件进行内容分发。

    注意,父组件中的标签必须有slot属性,且值为子组件中对应的slot名,这样父组件内容分发标签中的内容(即便没有内容,子组件插槽中的默认内容也不会显示出来,只有删除了父组件中对应的内容分发标签,才能显示出来)会覆盖掉子组件对应插槽中的默认内容

    //首先在子组件template模板部分中声明slot标签作为内容插槽,同时必须在其name属性中指定插槽名称,还可设置默认的标签内容
    <view class="panel">
        <slot name="title">默认标题</slot>
        <slot name="content">默认内容</slot>
    </view>
    
    //然后在引入了该带有插槽的子组件的父组件template模板部分中声明用于“插拔”的内容分发标签
    <panel>
        <view slot="title">新的标题</view>
        <view slot="content">
            <text>新的内容</text>
        </view>
    </panel>

    eg:message-com.wpy:

    <template>
    <!-- 1.4.6新增:循环渲染时(类似于原生的wx:for),必须使用WePY定义的辅助标签"<repeat>" -->
      <repeat for="{{messageList}}" index="index" item="message">
        <navigator url="/pages/topicDetail?topicId={{message.busiId}}">
          <view class="msgList">
            <!-- "<text selectable='true'>" 使文字可选-->
            <text selectable='true'>{{message.content}}</text>
            <view style="text-align: right;">
              <text style="color: rgb(202,202,202);">{{message.createTime}}</text>
            </view>
          </view>
        </navigator>
      </repeat>
    </template>
    <script>
      import wepy from 'wepy' //引入wepy
    
      export default class Message extends wepy.component {//创建组件实例
        props = {//接收父组件参数
          messageList: {// * 类型和默认值参数不能省略,组件会偶发性接收不到父组件传递的参数
            type: Array,
            default:[]
          }
        };
      }
    </script>
    <style scoped lang="less">
    
      .topicInfo text {
        font-size: 12px;
        color: #666;
      }
    
      .topicBottom view {
        margin-right: 15px;
      }
    
      .msgList {
        background-color: #fff;
        margin-top: 7px;
        padding: 10px 15px;
      }
    
    </style>

     message-page.wpy:

    <template>
      <view wx:if="{{!messageList.length}}" class="noData">暂无消息</view>
      <block wx:else>
        <message :messageList.sync="messageList"></message>
        <downLoad :show.sync="getListParam"></downLoad>
      </block>
    </template>
    
    <script>
      import wepy from 'wepy'
      import Message from '../components/message'
      import DownLoad from '../components/downLoad'
      import listMixin from '../mixins/list'
      import {connect} from 'wepy-redux'
      import {getMessageList} from '../store/actions'
    
      @connect({
        messageList(state) {
          return state.reducer.messageList;
        }
      }, {
        getMessageList
      })
    
      export default class MineMessages extends wepy.page {
        config = {
          navigationBarTitleText: '我的消息'
        };
        components = {
          message: Message,
          downLoad: DownLoad
        };
    
        data = {};
        mixins = [listMixin];
    
        methods = {
          getList(params) {
            let listParam = {
              messageType: 4
            };
            if (wx.getStorageSync('userId')) {
              this.getMessageList(Object.assign(listParam, params));
            } else {
              wx.showToast({
                title: '您还没有登录',
                icon: 'none'
              });
            }
          }
        };
      }
    </script>
    

    (2)mixins:Mixin 混合(公用的js)

    混合可以将组件之间的可复用部分抽离,从而在组件中使用混合时,可以将混合的数据,事件以及方法注入到组件之中。混合分为两种:

    • 默认式混合(data、components、events、自定义方法),即组件未声明的选项将混合对象中注入组件之中,组件已声明的选项将不受影响
    • 兼容式混合(methods响应事件 小程序页面事件),即先响应组件本身响应事件,然后再响应混合对象中响应事件(Vue则相反,先执行mixin中的函数, 再执行组件本身的函数

    eg:listMixin.js:

    import wepy from 'wepy'
    
    export default class ListMixin extends wepy.mixin {//创建mixin实例
      config = {
        enablePullDownRefresh: true,//开启下拉刷新,默认是关闭的
        onReachBottomDistance: 10,//设置触发下拉刷新的底部距离
        backgroundColor: "#eab010"//设置背景色
      };
      data = {
        getListParam: {//获取列表数据的通用参数
          hasMoreData: true,
          loading: false,
          noMore: false,
          page: 1,
          limit: 10,
        }
      };
    
      /**
       * 页面相关事件处理函数--监听用户下拉动作(下拉刷新)
       */
      onPullDownRefresh() {
        wx.showNavigationBarLoading(); //在标题栏中显示加载
        this.data.getListParam.page = 1;//下拉刷新时参数page=1
        this.methods.getList(this.data.getListParam);//调用组件中的获取列表函数
        setTimeout(() => {
          wx.hideNavigationBarLoading(); //完成停止加载
          wx.stopPullDownRefresh(); //停止下拉刷新
        }, 300)
      };
    
      /**
       * 页面上拉触底事件的处理函数(上拉加载)
       */
      onReachBottom() {
        if (this.data.getListParam.hasMoreData) {
          this.data.getListParam.page++;//每触发一次page++
          this.data.getListParam.hasMoreData = false;//关闭可调用函数
          this.data.getListParam.loading = true;//显示加载中...(自己写的底部加载中样式的组件)
          this.methods.getList(this.data.getListParam);//调用组件中的获取列表函数
          setTimeout(() => {
            this.data.getListParam.loading = false;//关闭显示加载中...(自己写的底部加载中样式的组件)
            this.$apply();//强制渲染
          }, 100);
        } else {
          this.data.getListParam.noMore = true;//显示加载完成(自己写的底部加载到底样式的组件)
        }
      };
    
      onReady() {
        this.methods.getList(this.data.getListParam);//初始化请求页面数据
      }
    
    }

    使用时引入然后注入到组件实例(最好放在data属性后,否则会偶发性报错),eg:

    (3)页面page.wpy

    Page页面实际上继承自Component组件,即Page也是组件。除扩展了页面所特有的config配置以及特有的页面生命周期函数之外,其它属性和方法与Component一致:

    import wepy from 'wepy';
    
    export default class MyPage extends wepy.page {
        customData = {}  // 自定义数据
    
        customFunction () {}  //自定义方法
    
        onLoad () {}  // 在Page和Component共用的生命周期函数
    
        onUnload() {}  // 监听页面卸载
    
        onReady() {}  //  只在Page中存在的页面生命周期函数
    
        onShow () {}  // 只在Page中存在的页面生命周期函数,当小程序启动,或从后台进入前台显示
    
        onHide() {}  // 只在Page中存在的页面生命周期函数,当小程序从前台进入后台
    
        config = {};  // 只在Page实例中存在的配置数据,对应于原生的page.json文件,类似于app.wpy中的config
    
        data = {};  // 页面所需数据均需在这里声明,可用于模板数据绑定
    
        components = {};  // 声明页面中所引用的组件,或声明组件中所引用的子组件
    
        mixins = [];  // 声明页面所引用的Mixin实例
    
        computed = {};  // 声明计算属性(详见后文介绍)
    
        watch = {};  // 声明数据watcher(详见后文介绍)
    
        methods = {};  // 声明页面wxml中标签的事件处理函数。注意,此处只用于声明页面wxml中标签的bind、catch事件,自定义方法需以自定义方法的方式声明
    
        events = {};  // WePY组件事件处理函数对象,存放响应组件之间通过$broadcast、$emit、$invoke所传递的事件的函数
    
        onPullDownRefresh(){}  // 监听用户下拉动作
    
        onReachBottom(){}  // 页面上拉触底事件的处理函数
    
        onShareAppMessage(){}  // 用户点击右上角分享
    
        onPageScroll(){}  // 页面滚动
    
        onTabItemTap(){}  //  当前是 tab 页时,点击 tab 时触发 
    }

    (4)状态管理store(redux)

    (5)app.wpy:小程序入口

    app.wpy实例继承自wepy.app类,包含:config配置对象(对应原生的app.json文件,build编译时会根据config属性自动生成app.json文件)、globalData全局数据对象、自定义方法与属性、小程序生命周期函数。

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

    <script>
    import wepy from 'wepy';
    export default class extends wepy.app {
        config = {
            pages:[// pages定义当前小程序所有页面路径,让微信客户端知道当前你的小程序页面定义在哪个目录
                'pages/index',
                'pages/mine'
            ],
            window:{//window定义小程序所有页面的顶部背景颜色,文字颜色定义等。
                "backgroundTextStyle": "light",
                "navigationBarBackgroundColor": "#fff",
                "navigationBarTitleText": "顶部标题",
                "navigationBarTextStyle": "black"
            },
            tabBar: {
                selectedColor: '#ea9100',//底部导航字体选中时的颜色
                list: [
                       {
                         pagePath: 'pages/index',//导航页面路径(必须在pages中定义)
                         text: '首页',//导航名
                         iconPath: 'img/index.png',//未选中的导航icon
                         selectedIconPath: 'img/index1.png'//选中时的导航icon
                       },
                       {
                         pagePath: 'pages/mine',
                         text: '我的',
                         iconPath: 'img/mine.png',
                         selectedIconPath: 'img/mine1.png'
                        }
                ]
           },
        };
        onLaunch() {//初始化
            console.log(this);
        }
    
        onShow(){}//当小程序启动,或从后台进入前台显示
        onHide(){}//当小程序从前台进入后台
    }
    </script>
    
    <style lang="less">
    /** less **/
    </style>

    (6)index.template.html:web页面的入口文件

    2、project.config.json小程序项目配置文件

    1.7.0 之后的版本会在根目录包含project.config.json,使用微信开发者工具-->添加项目项目目录请选择项目根目录即可根据配置完成项目信息自动配置。

    1.7.0 之前生成的代码包可能不存在project.config.json文件,建议手动创建该文件后再添加项目。project.config.json文件内容如下:

    {
      "description": "project description",
      "setting": {
        "urlCheck": true,//对应不检查安全域名选项,开启。 如果已配置好安全域名则建议关闭
        "es6": false,//对应关闭ES6转ES5选项,关闭。 重要:未关闭会运行报错
        "postcss": false,//对应关闭上传代码时样式自动补全选项,关闭。 重要:某些情况下漏掉此项也会运行报错
        "minified": false //对应关闭代码压缩上传选项,关闭。重要:开启后,会导致真机computed, props.sync 等等属性失效。(注:压缩功能可使用WePY提供的build指令代替)
      },
      "compileType": "miniprogram",
      "appid": "touristappid",
      "projectname": "Project name",
      "miniprogramRoot": "./dist"
    }

    3、wepy.config.js

    const path = require('path');
    var prod = process.env.NODE_ENV === 'production';
    
    module.exports = {
      /*wpyExt:缺省值为'.wpy',IDE默认情况下不会对此文件类型进行高亮处理
        除了进行前文代码高亮设置之外
        还可以直接将相关文件的后缀名由.wpy修改为.vue,然后将此选项修改为.vue
      */
      wpyExt: '.wpy',
      eslint: false,
      cliLogs: !prod,
      build: {
        web: {
          htmlTemplate: path.join('src', 'index.template.html'),
          htmlOutput: path.join('web', 'index.html'),
          jsOutput: path.join('web', 'index.js')
        }
      },
      resolve: {
        alias: {
          counter: path.join(__dirname, 'src/components/counter'),
          '@': path.join(__dirname, 'src')
        },
        aliasFields: ['wepy', 'weapp'],
        modules: ['node_modules']
      },
      /** compilers为1.3.1版本之后的功能,如果需要使用其它语法,请先配置compilers,然后再安装相应的compilers
         目前支持wepy-compiler-less, wepy-compiler-postcss,wepy-compiler-sass、wepy-compiler-babel、wepy-compiler-pug
         其他compiler持续开发中
       */
      compilers: {
        less: {
          compress: prod
        },
        /*sass: {
          outputStyle: 'compressed'
        },*/
        babel: {
          sourceMap: true,
          presets: [
            'env'
          ],
          /*
           plugins为1.1.6版本之后的功能
           目前支持js压缩wepy-plugin-ugliyjs、图片压缩wepy-plugin-imagemin
           其他plugin持续开发中
          */
          plugins: [
            'transform-class-properties',
            'transform-decorators-legacy',
            'transform-object-rest-spread',
            'transform-export-extensions',
          ]
        }
      },
      plugins: {},
    /*在使用的地方先引入import wepy from 'wepy'; 然后wepy.$appConfig.属性名。eg:wepy.$appConfig.baseUrl*/
      appConfig: {
        baseUrl:process.env.NODE_ENV === 'production'? 'https://api.a.com/' : 'https://api.a.com/dev/',
        noPromiseAPI: ['createSelectorQuery']
      }
    }
    
    if (prod) {
    
      // 压缩sass
      module.exports.compilers['less'] = {outputStyle: 'compressed'}
    
      // 压缩js
      module.exports.plugins = {
        uglifyjs: {
          filter: /\.js$/,
          config: {}
        },
        imagemin: {
          filter: /\.(jpg|png|jpeg)$/,
          config: {
            jpg: {
              quality: 80
            },
            png: {
              quality: 80
            }
          }
        }
      }
    }

    相关链接:mpvue文档原生小程序文档公众号文档

    博客地址:https://my.oschina.net/wangnian

    展开全文
  • 微信小程序开发框架—wepy快速入门

    万次阅读 2018-06-11 11:05:32
    小程序框架wepy文档Github地址wepy官网:https://tencent.github.io/wepy/index.html项目创建与使用安装wepy以下安装都通过npm安装安装 wepy 命令行工具。npm install wepy-cli -g 在开发目录生成开发DEMO。wepy...
    

    小程序框架wepy文档

    Github地址

    wepy官网:https://tencent.github.io/wepy/index.html

    项目创建与使用

    安装wepy

    以下安装都通过npm安装

    安装 wepy 命令行工具。

    npm install wepy-cli -g
    

    在开发目录生成开发DEMO。

    wepy new myproject
    

    开发实时编译。

    wepy build --watch
    

    项目目录结构

        dist
        node_modules
        src
            components
                com_a.wpy
                com_b.wpy
            pages
                index.wpy
                page2.wpy
            app.wpy
        package.json
    

    开发使用说明

    1. 使用微信开发者工具新建项目,本地开发选择dist目录。

    2. 微信开发者工具 --> 项目 --> 关闭ES6转ES5。

    3. 本地项目根目录运行wepy build --watch,开启实时编译。

    代码规范:

    1. 变量与方法使用尽量使用驼峰式命名,避免使用$开头。
      $开头的方法或者属性为框架内建方法或者属性,可以被使用,使用前请参考API文档

    2. 入口,页面,组件的命名后缀为.wpy。外链的文件可以是其它后缀。
      请参考wpy文件说明

    3. 使用ES6语法开发。
      框架在ES6下开发,因此也需要使用ES6开发小程序,ES6中有大量的语法糖可以让我们的代码更加简洁高效。

    4. 使用Promise
      框架默认对小程序提供的API全都进行了 Promise 处理,甚至可以直接使用async/await等新特性进行开发。

    主要解决问题:

    1. 开发模式转换

    在原有的小程序的开发模式下进行再次封装,更贴近于现有MVVM框架开发模式。框架在开发过程中参考了一些现在框架的一些特性,并且融入其中,以下是使用wepy前后的代码对比图。

    官方DEMO代码:

    //index.js
    //获取应用实例
    var app = getApp()
    Page({
      data: {
        motto: 'Hello World',
        userInfo: {}
      },
      //事件处理函数
      bindViewTap: function() {
        console.log('button clicked')
      },
      onLoad: function () {
        console.log('onLoad')
      }
    })
    

    基于wepy的实现:

    import wepy from 'wepy';
    
    export default class Index extends wepy.page {
    
        data = {
            motto: 'Hello World',
            userInfo: {}
        };
        methods = {
            bindViewTap () {
                console.log('button clicked');
            }
        };
        onLoad() {
            console.log('onLoad');
        };
    }
    

    2. 支持组件化开发。

    参见章节:组件
    示例代码:

    // index.wpy
    <template>
        <view>
            <component id="pannel" path="pannel"></component>
            <component id="counter1" path="counter"></component>
            <component id="counter2" path="counter"></component>
            <component id="list" path="list"></component>
        </view>
    </template>
    <script>
    import wepy from 'wepy';
    import List from '../components/list';
    import Panel from '../components/panel';
    import Counter from '../components/counter';
    
    export default class Index extends wepy.page {
    
        config = {
            "navigationBarTitleText": "test"
        };
        components = {
            panel: Panel,
            counter1: Counter,
            counter2: Counter,
            list: List
        };
    }
    </script>
    

    3. 支持加载外部NPM包。

    在编译过程当中,会递归遍历代码中的require然后将对应依赖文件从node_modules当中拷贝出来,并且修改require为相对路径,从而实现对外部NPM包的支持。如下图:

    [图片上传失败...(image-4ab3f4-1518177450772)]

    4. 单文件模式,使得目录结构更加清晰。

    官方目录结构要求app必须有三个文件app.jsonapp.jsapp.wxss,页面有4个文件 index.jsonindex.jsindex.wxmlindex.wxss。而且文件必须同名。
    所以使用wepy开发前后开发目录对比如下:
    官方DEMO:

    project
        pages
            index
                index.json
                index.js
                index.wxml
                index.wxss
            log
                log.json
                log.wxml
                log.js
                log.wxss
        app.js
        app.json
        app.wxss
    

    使用wepy框架后目录结构:

    project
        src
            pages
                index.wpy
                log.wpy
            app.wpy
    

    5. 默认使用babel编译,支持ES6/7的一些新特性。

    用户可以通过修改.wepyrc配置文件,配置自己熟悉的babel环境进行开发。默认开启使用了一些新的特性如promiseasync/await等等。

    示例代码:

    import wepy from 'wepy';
    
    export default class Index extends wepy.page {
    
        getData() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve({data: 123});
                }, 3000);
            });
        };
        async onLoad() {
            let data = await this.getData();
            console.log(data.data);
        };
    }
    

    6. 针对原生API进行优化。

    对现在API进行promise处理,同时修复一些现有API的缺陷,比如:wx.request并发问题等。
    原有代码:

    onLoad = function () {
        var self = this;
        wx.login({
            success: function (data) {
                wx.getUserInfo({
                    success: function (userinfo) {
                        self.setData({userInfo: userinfo});
                    }
                });
            }
        });
    }
    

    基于wepy实现代码:

    async onLoad() {
        await wx.login();
        this.userInfo = await wx.getUserInfo();
    }
    

    在同时并发10个request请求测试时:
    不使用wepy:

    [图片上传失败...(image-bacc86-1518177450770)]
    [图片上传失败...(image-d2d397-1518177450770)]

    使用wepy后:

    [图片上传失败...(image-d99a53-1518177450770)]

    进阶说明

    .wepyrc 配置文件说明

    执行wepy new demo后,会生成类似配置文件。

    {
      "wpyExt": ".wpy",
      "sass": {},
      "less": {},
      "babel": {}
    }
    

    wpyExt:缺省值为'.wpy',IDE默认情况下不会对此文件类型高亮,此时可以修改所有文件为.vue后缀(因为与vue高亮规则一样),然后将此选项修改为.vue,就能解决部分IDE代码高亮问题。

    sass:sass编译配置,参见这里

    less:less编译配置,参见这里

    babel:babel编译配置,参见这里

    wpy文件说明

    wpy文件的编译过程过下:

    [图片上传失败...(image-dc7981-1518177450770)]

    一个.wpy文件分为三个部分:

    1. 样式<style></style>对应原有wxss

    2. 模板<template></template>对应原有wxml

    3. 代码<script></script>对应原有js

    其中入口文件app.wpy不需要template,所以编译时会被忽略。这三个标签都支持typesrc属性,type决定了其代码编译过程,src决定是否外联代码,存在src属性且有效时,忽略内联代码,示例如下:

    <style type="less" src="page1.less"></style>
    <template type="wxml" src="page1.wxml"></template>
    <script>
        // some code
    </script>
    

    标签对应 type 值如下表所示:

    标签type默认值type支持值
    stylecsscsslesssass(待完成)
    templatewxmlwxmlxmlhtml(待完成)
    scriptjsjsTypeScript(待完成)

    script说明

    程序入口app.wpy

    <style type="less">
    /** less **/
    </style>
    <script>
    import wepy from 'wepy';
    export default class extends wepy.app {
        config = {
                "pages":[
                "pages/index/index"
            ],
            "window":{
                "backgroundTextStyle": "light",
                "navigationBarBackgroundColor": "#fff",
                "navigationBarTitleText": "WeChat",
                "navigationBarTextStyle": "black"
            }
        };
        onLaunch() {
            console.log(this);
        }
    }
    </script>
    

    入口app.wpy继承自wepy.app,包含一个config属性和其全局属性、方法、事件。其中config属性对应原有的app.json,编译时会根据config生成app.json文件,如果需要修改config中的内容,请使用系统提供API。

    页面index.wpy

    <style type="less">
    /** less **/
    </style>
    <template type="wxml">
        <view>
        </view>
        <component id="counter1" path="counter"></component>
    </template>
    <script>
    import wepy form 'wepy';
    import Counter from '../components/counter';
    export default class Index extends wepy.page {
    
        config = {};
        components = {counter1: Counter};
    
        data = {};
        methods = {};
    
        events = {};
        onLoad() {};
        // Other properties
    }
    </script>
    

    页面入口继承自wepy.page,主要属性说明如下:

    属性说明
    config页面config,相当于原来的index.json,同app.wpy中的config
    components页面引入的组件列表
    data页面需要渲染的数据
    methodswmxl的事件捕捉,如bindtapbindchange
    events组件之间通过broadcastemit传递的事件
    其它onLoadonReady等小程序事件以及其它自定义方法与属性

    组件com.wpy

    <style type="less">
    /** less **/
    </style>
    <template type="wxml">
        <view>  </view>
    </template>
    <script>
    import wepy form 'wepy';
    export default class Com extends wepy.component {
    
        components = {};
    
        data = {};
        methods = {};
    
        events = {};
        // Other properties
    }
    </script>
    

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

    组件

    小程序支持js模块化引用,也支持wxml模板,但彼此独立,业务代码与交互事件仍需在页面处理。无法实现组件化的松耦合与复用的效果。
    例如模板A中绑定一个bindtap="myclick",模板B中同样绑定一样bindtap="myclick",那么就会影响同一个页面事件。对于数据同样如此。因此只有通过改变变量或者事件方法,或者给其加不同前缀才能实现绑定不同事件或者不同数据。当页面复杂之后就十分不利于开发维护。
    因此wepy让小程序支持组件化开发,组件的所有业务与功能在组件本身实现,组件与组件之间彼此隔离,上述例子在wepy的组件化开发过程中,A组件只会影响到A绑定的myclick,B也如此。

    组件引用

    当页面或者组件需要引入子组件时,需要在页面或者script中的components给组件分配唯一id,并且在template中添加<component>标签,如index.wpy。

    页面和组件都可以引入子组件,引入若干组件后,如下图:

    [图片上传失败...(image-1316ae-1518177450768)]

    Index页面引入A,B,C三个组件,同时组件A和B又有自己的子组件D,E,F,G,H。

    组件通信与交互

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

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

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

    import wepy form 'wepy';
    export default class Com extends wepy.component {
    
        components = {};
    
        data = {};
        methods = {};
    
        events = {
            'some-event': ($event, ...args) {
                   console.log(`${this.name} receive ${$event.name} from ${$event.source.name}`);
            }
        };
        // Other properties
    }
    
    1. $broadcast
      $broadcast事件是由父组件发起,所有子组件都会收到此广播事件,除非事件被手动取消。事件广播的顺序为广度优先搜索顺序,如上图,如果Page_Index发起一个$broadcast事件,那么接收到事件的先后顺序为:A, B, C, D, E, F, G, H。如下图:

    [图片上传失败...(image-c6f17d-1518177450768)]

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

    [图片上传失败...(image-d5d6aa-1518177450768)]

    1. $invoke
      $invoke是一个组件对另一个组件的直接调用,通过传入的组件路径找到相应组件,然后再调用其方法。

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

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

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

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

    数据绑定

    小程序数据绑定方式

    小程序通过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);
    

    wepy脏数据检查流程

    在执行脏数据检查是,会通过this.$$phase标识当前检查状态,并且会保证在并发的流程当中,只会有一个脏数据检查流程在运行,以下是执行脏数据检查的流程图:

    [图片上传失败...(image-519e99-1518177450767)]

    其它优化细节

    1. wx.request 接收参数修改

    点这里查看官方文档

    // 官方
    wx.request({
        url: 'xxx',
        success: function (data) {
            console.log(data);
        }
    });
    
    // wepy 使用方式
    // request 接口从只接收Object变为可接收String
    wx.request('xxxx').then((d) => console.log(d));
    

    2. 优化事件参数传递

    点这里查看官方文档

    // 官方
    <view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>
    Page({
      tapName: function(event) {
        console.log(event.currentTarget.hi)// output: WeChat
      }
    });
    
    // wepy 建议传参方式
    <view id="tapTest" data-wepy-params="1-wepy-something" bindtap="tapName"> Click me! </view>
    
    events: {
        tapName (event, id, title, other) {
            console.log(id, title, other)// output: 1, wepy, something
        }
    }
    

    3. 改变数据绑定方式

    保留setData方法,但不建议使用setData执行绑定,修复传入undefined的bug,并且修改入参支持:
    this.setData(target, value)
    this.setData(object)

    点这里查看官方文档

    // 官方
    <view> {{ message }} </view>
    
    onLoad: function () {
        this.setData({message: 'hello world'});
    }
    
    // wepy
    <view> {{ message }} </view>
    
    onLoad () {
        this.message = 'hello world';
    }
    

    4. 组件代替模板和模块

    点这里查看官方文档

    // 官方
    <!-- item.wxml -->
    <template name="item">
      <text>{{text}}</text>
    </template>
    
    <!-- index.wxml -->
    <import src="item.wxml"/>
    <template is="item" data="{{text: 'forbar'}}"/>
    
    <!-- index.js -->
    var item = require('item.js')
    
    // wepy
    <!-- /components/item.wpy -->
     <text>{{text}}</text>
    
    <!-- index.wpy -->
    <template>
        <component id="item"></component>
    </template>
    <script>
        import wepy from 'wepy';
        import Item from '../components/item';
        export default class Index extends wepy.page {
            components = { Item }
        }
    </script>
    
    

    API

    wepy.event

    属性类型默认值说明
    nameString-事件名称
    sourcewepy.component-事件来源
    typeString-emit 或者 broadcast
    方法参数返回值说明
    destroy--在 emit 或者 broadcast 过程中,调用destroy方法将会停止事件传播。

    wepy.component

    属性类型默认值说明
    isComponentBooleantrue是否是组件,如果是页面,此值为false
    prefixString''组件前缀,组件前缀+组件方法属性才是在小程序中真实存在的方法或属性。
    $rootwepy.page-根组件,一般都是页面
    $parentwepy.component-父组件
    $wxpagePage-小程序Page对象
    $comsList(wepy.component){}子组件列表
    方法参数返回值说明
    init--组件初始化。
    getWxPage-Page返回小程序Page对象。
    $getComponentpath(String)wepy.component通过组件路径返回组件对象。
    $invokecom(String/wepy.component), method(String), [args]-调用其它组件方法
    $broadcastevtName(String), [args]-broadcast事件。
    $emitevtName(String), [args]-emit事件。
    $applyfn(Function)-准备执行脏数据检查。
    $digest--脏检查。

    wepy.page

    方法参数返回值说明
    init--页面始化。

    wepy.app

    属性类型默认值说明
    $wxappApp-小程序getApp()
    init--应用始化包括对原生API的改造与优化


    作者:傻梦兽
    链接:https://www.jianshu.com/p/c34a7cc08fc8
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    展开全文
  • wepy的基本安装和使用

    2019-11-15 09:49:25
    wepy的基本使用使用 1、WePY 简介和安装 001 - 什么是 WePY WePY 是腾讯官方出品的一个小程序快速开发框架,对原生小程序的开发模式进行了再次封装 wepy官网 002 - 为什么使用 WePY WePY 相比于原生小程序开发,...

    wepy的基本使用

    1、WePY 简介和安装
    001 - 什么是 WePY

    WePY 是腾讯官方出品的一个小程序快速开发框架,对原生小程序的开发模式进行了再次封装

    wepy官网

    002 - 为什么使用 WePY

    WePY 相比于原生小程序开发,拥有众多的开发特性和优化方案,

    • 开发风格接近于 Vue.js,支持很多vue中的语法特性;
    • 通过 polyfill 让小程序完美支持 Promise;
    • 可以使用ES6等诸多高级语法特性,简化代码,提高开发效率;
    • 对小程序本身的性能做出了进一步的优化;
    • 支持第三方的 npm 资源;
    • 支持多种插件处理和编译器;
    003 - 安装 WePY
    • WePY 的安装或更新都通过 npm 、yarn、cnpm进行全局安装
    npm install wepy-cli -g
    
    004 - 初始化 WePY 项目
    • 使用命令行方式进行初始化项目结构

      • wepy init standard myproject
      • wepy init – 是固定写法,代表要初始化 wepy 项目;
      • standard – 代表模板类型为标准小程序模板
      • myproject – 为自定义的项目名称。
    • Project name () :项目的名字可以更改,如果不修改直接回车即可

    • AppId (touristappid):输入自己小程序的Appid

    • Project description:项目的描述,直接回车即可

    • Author ():项目作者,直接回车

    • Use ESLint to lint your code? (Y/n):真正开发的时候建议开启,现在学习阶段,先不开启

    • Use Redux in your project?:是否使用Redux框架语法,目录会多出store目录,no

    • Use web transform feature in your project?:是否开启web转换,no

    005- WePY 和 小程序项目的关系
    • 通过 wepy init 命令初始化的wepy 项目,实际是一个模板项目,不能直接当作小程序运行。
    • 需要运行相关的命令,把模板项目编译为小程序项目,才可以运行。

    02 - wepy项目介绍

    2.1 - wepy项目运行
    001 - 运行编译 WePY 项目
    • 运行 cd myproject 切换至 `WePY`` 项目根目录
    • 运行 npm install 安装 WePY 项目依赖项
    • 运行 wepy build --watch 开启实时编译
      • wepy build --watch 命令,会循环监听 WePY项目中源代码的变化,自动编译生成小程序项目

    注意:生成的小程序项目默认被存放于 dist 目录中。

    002 - 认识WePY 项目目录

    在这里插入图片描述

    003 - 将 WePy 项目导入到开发者工具中
    • 在微信开发者工具中选择导入项目,选择项目的根目录即可
    • 可以用vscode打开wepy项目
    2.2、WePY 文件介绍
    001 - 介绍.wpy文件的组成部分
    • 一个 .wpy 文件可分为三大部分,各自对应于一个标签:
      • 脚本部分,即 <script></script> 标签中的内容,又可分为两个部分:
        • 逻辑部分,除了 config 对象之外的部分,对应于原生的 .js 文件
        • 配置部分,即 config 对象,对应于原生的 .json 文件
      • 结构部分,即 <template></template> 模板部分,对应于原生的 .wxml 文件。
      • 样式部分,即<style></style>样式部分,对应于原生的 .wxss 文件。
    • 其中,小程序入口文件 app.wpy 不需要 template,所以编译时会被忽略。
    002- 小程序入口 app.wpy

    app.wpy主要分为两大部分script和style

    • config 属性会被编译为小程序的 app.json 全局配置文件;
    • config 属性之外的其它节点,会被编译为小程序的 app.js 文件;
    • style 标签会被编译为小程序的 app.wxss 全局样式;
    003 - app.wpy 全局配置小程序外观

    在小程序的入口文件中找到 window 节点:app.wpy -> script标签 -> config -> window 即可全局配置小程序的外观

    window: {
      backgroundTextStyle: 'dark',
      navigationBarBackgroundColor: '#fff',
      navigationBarTitleText: '小程序电商项目',
      navigationBarTextStyle: 'black'
    }
    
    004 - 页面 .wpy 文件中 script 标签组成结构

    页面文件 page.wpy 中所声明的页面实例继承自 wepy.page

    属性 说明
    config 页面配置对象,对应于原生的page.json文件,类似于app.wpy中的config
    components 页面组件列表对象,声明页面所引入的组件列表
    data 页面渲染数据对象,存放可用于页面模板绑定的渲染数据
    methods wxml事件处理函数对象,存放响应wxml中所捕获到的事件的函数,如bindtapbindchange
    computed 和vue的计算属性是一样的
    onLoad 小程序页面生命周期函数
    005 - 尝试修改window窗口外观
    • 通过修改app.wpy里面的config》window来配置窗口外观

    03-wepy的基本使用

    3.1创建页面和事件绑定

    如何设置默认首页

    • 在pages文件夹下面新建home.wpy文件

    • 定义基本的结构

      <template>
      
      </template>
      
      <script>
      
      import wepy from 'wepy'
      
      export default class Home extends wepy.page {
        data = {
        }
      
        config = {
        }
      
        methods = {
      
        }
      }
      
      </script>
      
      <style lang='less'>
      
      </style>
      
    • 配置用户代码片段,文件》首先项》用户代码片段》新建全局用户代码片段,取名wepy回车创建,将代码片段复制进文件内部即可

    • 将home.wpy路劲配置到全局的app.wpy下面的pages里面,并且是第一个

    页面绑定事件以及传参

    wepy 框架中,优化了事件绑定机制,支持类似于 Vue.js的事件绑定语法

    • WePY 中,统一使用 @ 绑定事件,传递参数直接采用@tap='handle({{params}})'传递
    • 案例代码
    <button type="primary" size="mini" @tap="tapHandle({{count}},{{count2}})">点我啊,老弟</button>
    
    data = {
      msg: '锄禾日当午,汗滴禾下土,这是四个人',
      count:10,
      count2:20
    }
    
    config = {
    }
    
    methods = {
      tapHandle (num,num2) {
        console.log(num,num2)
      }
    }
    
    • 如果想获取到事件对象,默认不传递参数,第一个形参为事件对象
    • 如果即想要传参还想要获取到事件对象,可以采取data-自定义属性的形式传参

    页面绑定事件关于事件函数和非事件函数的注意事项

    • 事件函数我们定义在methods里面
    • 非事件函数我们推荐定义在methods同级的下面
    3.2文本框和数据绑定同步
    • 案例逻辑:

      • 首先在data里面准备数据,并渲染到input输入框中

        data = {
          count: 10,
          value: '我和陆游说,我比较喜欢李白的诗,陆游气坏了,然后我家没网了'
        }
        
        <input type="text" value="{{value}}">
        
      • 给输入框注册input事件监听输入框的变化

        <input type="text" value="{{value}}" @input="inputHandle">
        
      • 在事件处理函数内部拿到最新的输入框的值,并同步给数据

        methods = {
          inputHandle (e) {
            console.log(e.detail.value)
            this.value = e.detail.value
          }
        }
        

    04 - wepy的request请求

    4.1wepy发送请求

    WePY 框架对原生小程序做了封装,之前通过 wx 调用的 API,都可以直接使用 wepy 进行调用

    • 利用wepy调用原生的方法

      wepy.request({
        url: 'url',
        success(res){
          console.log(res)
        }
      })
      
    • 修改成基于promise的形式,结果发现报错不支持

      wepy.request({
        url: 'url
      }).then(res=>{
        console.log(res)
      })
      

    配置 promisify 启用 asyncawait

    • 默认使用 wepy-cli 创建的项目,不支持使用 ES7asyncawait 来简化 Promise API 的调用。

    • 需要手动开启此功能:打开 src -> app.wpy,找到 constructor() 构造函数,在构造函数中代码的最后一行,添加 this.use(‘promisify’)

      constructor () {
        super()
        this.use('requestfix')
        this.use('promisify')
      }
      
    • 基于promise使用wepy发送get请求

      // wepy 发送 Get 请求
      
      wepy.request({
        url: 'url',
        data:{
          age: 18
        }
      }).then(res=>{
        console.log(res)
      })
      
    • 利用async和await简化promise

      async getData () {
        const res = await wepy.request({
          url: 'url',
          data:{
            age: 18
          }
        })
        console.log(res)
      }
      
    4.2异步更新数据

    在异步函数中更新数据的时候,必须手动调用 this.$apply 方法。

    const res = await wepy.request({
      url: 'url',
      data:{
        age: 18
      }
    })
    console.log(res)
    this.value = res.data.data.age
    this.$apply()
    

    #####4.3发送post请求

    async postData () {
      const res = await wepy.request({
        url: 'url',
        method: 'post',
        data:{
          age: 18
        }
      })
      console.log(res)
    }
    
    展开全文
  • wepy-小程序开发框架学习(一)

    千次阅读 2018-05-22 10:30:20
    一、安装npm由于新版的NodeJS已经集成了npm,我们可以安装NodeJS来实现安装npm。...安装完成以后验证npm是否安装成功:运行cmd命令npm -v得到如下图所示,我的版本是6.0.0表示安装成功。二、安装we...
  • wepy框架源码

    2020-07-24 23:32:22
    小程序wepy框架代码实例 商城开发源码
  • wepy框架入门

    千次阅读 2019-05-18 11:44:58
    安装 wepy 命令行工具。 npm install wepy-cli -g 在开发目录生成开发DEMO。 wepy new myproject 开发实时编译。 wepy build --watch 项目目录结构 dist node_modules src components com_a.wpy com...
  • wepy:搭建小程序教程(一)

    千次阅读 2019-04-28 12:12:11
    1.在使用wepy搭建小程序前必须全局安装wepy包,使用 npm install wepy-cli-g 2.在下图可以看到创建一个wepy的命令是wepy new myproject(以前的办法), 现在统一创建使用的命令为wepy init standard myproject ...
  • 小程序发展到了今天,已经开放出了太多的利好消息,API 也已经非常丰富和完善了。但是开发小程序,很多时候非常繁琐,这个原因是小...答案是:WePYWePY是腾讯开源的一个小程序开发框架,注意,是腾讯开源的。We...
  • wepy框架入门教程

    千次阅读 2019-05-27 16:57:05
    wepy快速指南 小程序框架wepy开发文档 wepy开源 wepy官方文档 ###1:安装node 端开发框架和环境都是需要 Node.js ,先安装node.js开发环境,WePY借鉴了Vue.js(后文简称Vue)的语法风格和功能特性,vue的运行是要...
  • wepy项目的创建及打包

    千次阅读 2018-07-21 14:13:34
    安装wepy-cli,建立新项目   安装Sass  npm install node-sass  npm install wepy-compiler-sass --save-dev 配置wepy.config.js /**********************************/ wepy项目打包 用于区分开发...
  • wepy的安装步骤

    万次阅读 2018-06-27 22:21:26
    1、使用官方文档的安装步骤,打开黑窗(window+R)...npm install wepy-cli -g 2)wepy init standard myproject 这是有内容的文件夹(有各种示例),可以建空的文件夹 wepy --help wepy list 根据提示更改数据 ...
  • 内网环境下wepy init standard my-project报如下错误 C:\Users\CPIC&gt;wepy init standard my-project | downloading template wepy-cli · Failed to download repo standard: connect ETIMEDOUT 151.101.108...
  • wepy中的页面跳转

    千次阅读 2018-12-05 11:04:31
    1.在pages中创建好页面之后,需要在app.wpy中的config中配置好页面路由; 2.如果跳转的按钮在page页面中 this.$navigate({url:"content"}) 3.如果跳转的按钮在子... wepy.navigateTo({ url: '/pages/...
  • 1.要使用async/await,得先安装wepy-async-function npm installwepy-async-function 2.在app.wpy文件里引入wepy-async-function import ‘wepy-async-function’ 3.采用promise封装异步请求的API 在这里的...
  • wepy 图片路径的问题

    千次阅读 2018-05-18 15:48:36
    如果不希望小程序引入的图片的路径不被修改,可以改写一下写法 &lt;image src="{{'./images/1.jpeg'}}" /&gt;
  • 小程序学习——打开wepy项目

    千次阅读 2018-04-11 14:08:03
    微信开发者工具打开已有的wepy项目wepy项目是依赖npm的,所以在clone下来后,1.进入目录下,npm install2,运行 wepy build --watch,开启实时编译确认无误时,我们打开微信开发者工具,1.新建项目 2,填写如下,一定要...
  • wepy中的生命周期

    千次阅读 2018-12-06 10:08:18
    wepy中的生命周期的钩子函数有:onLoad,onReady,onShow,onPrefetch等,其中onReady,onShow,onPrefetch只有wepy.page中才有用。wepy.component只支持onLoad,其他都不会触发。 &lt;style lang="less&...
  • 微信小程序框架wepy之动态控制类名

    千次阅读 2017-11-05 20:38:25
    控制类名 style .liBkgCor { background-color: red; } template ({{1}})" class="{{ liColor == 1 ? 'liBkgCor':''
1 2 3 4 5 ... 20
收藏数 3,578
精华内容 1,431
关键字:

wepy