精华内容
参与话题
问答
  • 快速入门 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 开发的小程序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: 对应不检查安全域名选项,开启。 如果已配置好安全域名则建议关闭。

    展开全文
  • WePY1 vs WePY2

    2020-04-13 09:50:04
    1、什么是WePY 微信小程序组件化开发框架WePY。将 Web App 和小程序进行对比。Web App 和小程序在功能上类似, Web App 在开发的时候,可能使用 Vue.js 作为其核心库,用 Webpack 进行打包。在微信小程序中,大家...

     

    1、什么是WePY

    微信小程序组件化开发框架WePY。将 Web App 和小程序进行对比。Web App 和小程序在功能上类似, Web App 在开发的时候,可能使用 Vue.js 作为其核心库,用 Webpack 进行打包。在微信小程序中,大家可以简单的将 WePY 理解为 Web App 里的 Vue.js + Webpack 的合体。

     

    官方介绍:

    WePY (发音: /'wepi/) 项目启动于 2017 年 11 月份, 是小程序最早的框架之一,是一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。框架的细节优化,Promise,Async Functions的引入都是为了能让开发小程序项目变得更加简单,高效。

     

    其他框架:Taro、uni-app、mpvue....

     

    2、WePY1 vs WePY2

     

    1.入口申请调整

    WePY 1 使用类的继承方式 export default class MyPage extends wepy.page {}

     

    WePY 2 中调整为 wepy.page({})。将实例化的过程放在生命周期事件中。

    在 WePY2 的环境当中,每个 WePY2 页面拥有独自的 WepyPage 实例。小程序也会有 WepyApp 实例。它们并非是继承自原生的 Page 和 App。WePY 提供 wepy.app,wepy.page,wepy.component 等入口 方法注册程序、页面、以及组件。注册后在组件的生命周期事件(onLaunch/onLoad/created)里,会自动创建相对应的 WePY 实例。

     

    2.数据绑定机制调整

    WePY 1 使用脏检查进行数据绑定,在异步函数中更新数据的时,必须手动调用$apply方法 WePY 2 中使用了 Vue Observer 实现数据绑定,不需要使用$apply()。

     

    Vue Observer:https://segmentfault.com/a/1190000008377887?utm_source=tag-newest

     

     

    3.避免文件编译时出现的问题

    WePY 1 是通过文件编译创建的静态组件在动态循环遍历时会出现一些问题:

    组件使用的是静态编译组件,即组件是在编译阶段编译进页面的,每个组件都是唯一的一个实例,目前只提供简单的 repeat 支持。不支持在 repeat 的组件中去用 props, computed, watch 等等特性。

    WePY 2直接基于的小程序原生的组件去实现,避免了这一类问题。

     

     

    4.Vue 模板语法

    WePY 1 使用wxml来写 template

    WePY 2中推荐使用 html 代替 wxml 来写 template,支持除 filter 之外的所有 Vue 模板语法。

     

     

    5.编译方式改变

    WePY 1 默认使用babel编译,基于文件编译

    WePY 2 从基于文件编译调整为基于入口编译,对于图片等静态资源需要指定 static 选项 。

     

    babel:https://www.babeljs.cn/docs/

     

    6.组件引用方式

    WePY 1 使用 import 的方式导入

    WePY 2 中使用原生的 usingComponents 方式

     

     

    7.单文件组成

    WePY 1 : <script>,<template>,<style>

    WePY 2 : <script>,<template>,<style>,<config>

     

    8.二者不兼容

    需要注意的是,WePY 1 的 cli 工具和 WePY 2 的 cli 工具并不能兼容和共存, WePY 1 的 cli 工具无法编译 WePY 2 的项目,同理 WePY 2 的 cli 工具也无法编译 WePY 1 的项目。在使用 npm 的 --global 参数安装时,将会进行版本覆盖。

     

     

    3、其他

    文档:

    https://wepyjs.github.io/wepy-docs/1.x/

    https://wepyjs.github.io/wepy-docs/2.x/#/

     

    4、uni-app

    uni-app 使用vue的语法+小程序的标签和API。

     

    文档:https://uniapp.dcloud.io/README

     

    开发注意:

    1、单文件模式;

    2、组件标签靠近小程序 <view></view> ....;

    3、接口能力(JS API)靠近微信小程序规范,但需将前缀 wx 替换为 uni;

    4、为兼容多端运行,建议使用flex布局进行开发;

    5、页面样式:早期 uni-app 提供了 upx ,目前已经推荐统一改为 rpx ;

    6、目录结构:

    ┌─components uni-app组件目录

    │ └─comp-a.vue 可复用的a组件

    ├─hybrid 存放本地网页的目录

    ├─platforms 存放各平台专用页面的目录

    ├─pages 业务页面文件存放的目录

    │ ├─index

    │ │ └─index.vue index页面

    │ └─list

    │ └─list.vue list页面

    ├─static 存放应用引用静态资源(如图片、视频等)的目录,

    注意:静态资源只能存放于此

    ├─wxcomponents 存放小程序组件的目录

    ├─main.js Vue初始化入口文件

    ├─App.vue 应用配置,用来配置App全局样式以及监听

    ├─manifest.json 配置应用名称、appid、logo、版本等打包信息

    └─pages.json 配置页面路由、导航条、选项卡等页面类信息

     

    7、生命周期

    应用生命周期,只可在App.vue中监听,常用函数:

    onLaunch

    当uni-app 初始化完成时触发(全局只触发一次)

    onShow

    当 uni-app 启动,或从后台进入前台显示

    onHide

    当 uni-app 从前台进入后台

    onError

    当 uni-app 报错时触发

    页面生命周期,常用:

    onLoad

    监听页面加载,其参数为上个页面传递的数据,参数类型为Object(用于页面传参)

    onShow

    监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面

    onReady

    监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发

    onHide

    监听页面隐藏

    onUnload

    监听页面卸载

    展开全文
  • WePY 2.x 安装 pug

    2019-12-27 17:38:24
    wepy1.0,直接使用 npm install pug 来安装是没有问题的,可是在wepy2.0的版本会报错 这里说需要安装插件 wepy-compiler-pug,按照这个报错信息,我们直接安装npm install wepy-compiler-pug --save-dev ,然后在...

    在wepy1.0,直接使用 npm install pug 来安装是没有问题的,可是在wepy2.0的版本会报错
    在这里插入图片描述
    这里说需要安装插件 wepy-compiler-pug,按照这个报错信息,我们直接安装npm install wepy-compiler-pug --save-dev ,然后在wepy.config.js配置
    pug: {
    pretty: false
    },
    在这里插入图片描述
    依然报错,还是找不到wepy-compiler-pug,Not Found - GET https://registry.npmjs.org/@wepy%2fcompiler-pug - Not found
    这里可以看到,指向的插件库找不到wepy-compiler-pug,所以导致安装失败了。
    既然这个默认的官方插件库找不到,我们就找其他的插件库
    于是找到了这个地址
    https://github.com/Riant/wepy2-compiler-pug.git#master -D
    如果你是yarn
    yarn add @wepy/compiler-pug@https://github.com/Riant/wepy2-compiler-pug.git#master -D
    如果你是npm
    npm install @wepy/compiler-pug@git+https://github.com/Riant/wepy2-compiler-pug.git#master --save-dev

    等待下载完成之后 wepy build --watch 运行项目,如果还是不行,建议先删除node_modules 和打包文件,重新打包 npm install 再 wepy build --watch 如果可以运行,那恭喜。

    ----------------结尾
    ---------------本人是菜鸟一枚,有待提升,大家共同学习--------

    展开全文
  • 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-02-02 14:50:48
    由于工作上的原因,有需求要使用 WePy,刚好,有了云开发的契机,就决定研究一下。 初试 WePY 想要做云开发和 WePY,首先要先熟悉 WePYWePY 其实之前就听说过,不过自己一直没有使用,更多还是习惯用小程序原生...
  • wepy的基本安装和使用

    2019-11-15 09:42:21
    wepy的基本使用使用 1、WePY 简介和安装 001 - 什么是 WePY WePY 是腾讯官方出品的一个小程序快速开发框架,对原生小程序的开发模式进行了再次封装 wepy官网 002 - 为什么使用 WePY WePY 相比于原生小程序开发,...
  • 小程序发展到了今天,已经开放出了太多的利好消息,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-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 框架

    2020-02-13 20:29:14
    WePY 是 腾讯官方出品的一个小程序快速开发框架,对原生小程序的开发模式进行了再次封装,更贴近于MVVM 架构模式,并支持 ES6 / 7 的一些新特性,同时语法风格更接近于Vue.js ,使用 WePY 框架能够提高小程序的开发...
  • wepy框架

    千次阅读 2017-09-22 18:09:58
    wepy框架 1、使用微信开发者工具新建项目,本地开发选择dist目录。 2、编辑是src文件 3、放入微信开发工具时把开启各种检验给关闭 4、注意小程序下边事件会覆盖上边的,把无用的事件删掉
  • 微信小程序是一种不需要下载安装即可使用的应用,在国内它在企业推广中的受欢迎度以及就这两年的使用及普及热度,然而就是因为它的备受欢迎度以及越来越被企业所重视,也就形成了咱们开发人员对小程序的开发的掌握;...
  • wepy框架源码

    2018-09-13 19:25:51
    小程序wepy框架代码实例 商城开发源码
  • 文章目录一、环境配置1、安装node2、设置淘宝源3、小程序开发必备4、安装vscode5、使用说明二、开始搭建1、前期初始化项目2、安装scss(可不装) 一、环境配置 1、安装node ... 查看node版本号: node -v ...
  • 微信小程序wepy框架笔记

    万次阅读 2018-01-30 20:14:48
    框架是腾讯内部基于小程序的开发框架,设计思路基本参考VUE,开发模式和编码风 格上80%以上接近VUE 优势 组件化开发 小程序虽然有标签可以实现组件复用,但仅限于模板片段层面的复用,业务代码与交互事件 仍...
  • wepy框架搭建小程序

    千次阅读 2019-03-28 20:46:04
    我们都知道,小程序对组件化开发并不友好,腾讯自己的 团队就搞出了一个wepy框架。我们先看下wepy的介绍; 既然说自己是最受欢迎的小程序 框架,我们就来安装使用一下吧; 步骤 : 1:npm install wepy-cli -d...
  • 微信小程序开发之wepy框架

    千次阅读 2018-06-19 20:11:01
    wepy是由腾讯团队推出的小程序组件化开发框架,为什么一开始推出的时候不直接用这一套!?官网地址 WePY 是一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。...
  • 在index.wpy的onload中插入 ...wepy.showShareMenu({ withShareTicket: true }) //在onShareAppMessage中设置分享的界面,**onShareAppMessage和onload同级** onShareAppMessage( options ){ var that = ...
  • 微信小程序 wepy框架 消息提示插件
  • 基础 全局配置 1.window项配置 enablePullDownRefresh和onReachBottomDistance这两项如果在页面内有下拉加载更多数据的情况下,需要设置相应的值 navigationStyle值为custom时导航栏需自定义,只保留右上角的...
  • wepy——微信小程序的一种框架 简述 由于项目原因,我于两个多月前转到微信端用wepy进行开发。wepy开发风格接近于 Vue.js,支持组件 Props 传值,自定义事件、组件分布式复用Mixin、Redux、计算属性函数computed、...
  • 使用wepy框架编辑

    2018-07-17 18:12:59
    Windows 下安装NPM 第一步: 下载node.js的windows版 ...   第二步:设置环境变量 把node.exe所在目录加入到PATH环境变量中。...配置成功后可以在CMD中通过node --version 看到node.js对应的版本号 ...
  • wepy框架中使用echarts

    千次阅读 热门讨论 2018-08-18 11:29:11
    echarts-for-wexin目前提供的方式是在原生小程序中的使用,直接将其中的ec-canvas作为组件在wepy的页面中使用可能会出现问题,并不能达到渲染的效果 我最开始的使用方式是这样的: &amp;amp;amp;amp;amp;...
  • 【安装指令】npm install wepy-cli -g  -g:全局安装 注:以管理员身份打开命令行(如果不是管理员身份,可能出错) (出错情况)   (成功情况:橙色框是版本号)   注: 先检查是否安装node(可能...
  • 初学wepy框架 重项目搭建到开发的流程,配合小程序开发工具完成项目的整体开发 这是一个基于vue的小程序的开发框架,我们不能直接在小程序开发框架中去编写我们的代码,因为它解析不了wpy。建议大家用VS code去编辑...
  • 最近一直在玩 B 站, 然后发现B站里面有骨架镜的功能,因为之前在写小程序的时候也想用,但是无奈项目紧迫没时间研究,然后今天花了一天的时间,下面说说如何应用。 理想是 写一个组件,然后各个页面只要引入该组件...
  • 第一步: 安装node.js:https://nodejs.org/zh-cn/ ...(成功后可使用命令行: cnpm install xxx) 第二步: 安装wepy-cli脚手架 cnpm install wepy-cli -g 或者 cnpm install @wepy/cli -g 第三步: 生成开发实例 wep
  • 一、微信小程序wepy框架简介: 微信小程序WePY框架是腾讯官方推出来的框架,类似的框架还有美团的mpvue,京东的Taro等; 目前公司开发小程序主要用到的是微信原生方法和官方的wepy框架; wepy框架在开发过程中参考了 Vue ...

空空如也

1 2 3 4 5 ... 20
收藏数 4,173
精华内容 1,669
关键字:

wepy