Quick Start WePY Mini Program

1. Introduction to WePY

WePY is  a framework for re-encapsulating native applets by Tencent  with reference to Vue and other frameworks. It is closer to the MVVM architectural pattern and supports some new features of ES6/7.

2. Use of WePY

1. The installation or update of WePY is done npmby:

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) Install or update wepy-cli globally:

(2) Check the wepy-cli version:

(3) Create a wepy applet project:

(4) Switch to the project directory and install dependencies:

(5) Turn on real-time compilation

2. Code highlighting WebStorm/PhpStorm (for other tools, see : wepy official website code highlighting )

(1) Open Settings, search Plugins, search for the Vue.jsplugin and install it.

(2) Open Settings, search File Types, find Vue.js Template, and Registered Patternsadd *.wpyto highlight.

3. Code optimization

(1) Code specification

  • wepy tags are the same as native
  • Custom component names should be avoided: native component names ( input、button、view、repeatetc.), WePY auxiliary tags<repeat>
  • The variable/method name should be named in camel case as much as possible, and avoid using the $beginning ( $the identifier at the beginning is the built-in property/method of WePY, which can be this.used directly in js, please refer to the API documentation for details )
  • The file name suffix of app, pages, and components is .wpy, and the external chain file can have other suffixes. For details, please refer to the description of the wpy file .
  • It supports some new features of ES6/7. The framework is developed under ES6 (ECMAScript 6) (compiled with babel by default), so it is also necessary to use ES6 to develop small programs. There are a lot of syntactic sugars in ES6 to make our code more concise and efficient.
  • Wepy inherits the method of the wx object. It is recommended not to use the method of the wx object in the development of the wepy framework. Although the runtime effect is the same, the cli will report an error when packaging (there is no wx object in wepy). The component in wepy uses class , Objects are used in vue.

(2) Data binding

The applet page rendering layer is separated from the JS logic layer. The setData operation is actually the communication between the JS logic layer and the page rendering layer. When the setData operation is performed multiple times in the same running cycle, the number of times of communication depends on whether it is one or more times. in the design of the API itself. WePY uses dirty data check to encapsulate setData, and performs dirty data check at the end of the function running cycle. First, you don't need to care about whether the page will have performance problems when setData multiple times. Second, it can be more concise to modify data to achieve binding. There is no need to repeatedly write the setData method.

//原生小程序
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) Event binding and parameter optimization

<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) By default, the framework handles all the APIs provided by the applet with promises, and can even use async/awaitnew features such as directly for development, and fixes some defects of the native API (such as concurrency problems of wx.request, etc.)

// 原生代码:

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 property A computedcomputed property ( type{ [key: string]: Function }) is a function with a return value that can be used directly as bound data, similar to dataproperties. Note that all computed properties will be recomputed whenever any data in the component changes.

  data = {
      a: 1
  }

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

(6) watcher listener

By listener watcher(type{ [key: string]: Function })Can listen to any property update. Listeners are useful when some additional processing is required when a property changes.

  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 supports wxs syntax since 1.7.x version, but the syntax is slightly different from native wxs

a.wxs is implemented based on native wxs, but compiles the current syntax into native syntax by compiling

②wxs must be an external link file. and suffixed with.wxs

③ After wxs is introduced, it can only be used in template, not in 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 interceptor

Native API requests can be intercepted using the global interceptor provided by WePY. The specific method is to configure the API's config, fail, success, and complete callback functions. Reference example:

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

3. The directory structure of the WePY project

The dist directory is the directory generated by WePY through the build command. Except for the additional npm directory, its directory structure is similar to that of the native applet.

Native applet: app( app.js, app.json, app.wxss), page( page.js, page.json, , page.wxmland page.wxss),files must have the same name. WePY uses single-file mode: app.wpy, page.wpy.

 ==> 

A .wpyfile can be divided into three parts, each corresponding to a tag:

  1. The script <script>part can be divided into two parts:

    The logical part, except the part other than the config object, corresponds to the native .jsfile

    The configuration part, the config object, corresponds to the native .jsonfile

  1. Structure <template>part, corresponding to the native .wxmlfile

  2. style <style>section, corresponding to the native .wxssfile

<!--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

Mainly analyze the following points of the directory (the detailed explanation of other directory files is similar to the analysis done in https://my.oschina.net/wangnian/blog/2050375 ):

1. src folder

(1) components component:

Component instances inherit from wepy.componentclasses, configand their properties are roughly the same as page properties, except that they do not require configuration and some page-specific lifecycle functions:

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事件,自定义方法需以自定义方法的方式声明,不能放在methods中,会报错
    events = {};  // WePY组件事件处理函数对象,存放响应组件之间通过$broadcast、$emit、$invoke所传递的事件的函数
}
/** 与page不同的是component不存在:
    onShow () {}  // 只在Page中存在的页面生命周期函数
    config = {};  // 只在Page实例中存在的配置数据,对应于原生的page.json文件,类似于app.wpy中的config
    onReady() {}  //  只在Page中存在的页面生命周期函数
**/

The native applet supports js modularization , but is independent of each other, and business code and interaction events still need to be processed on the page. Unable to achieve loose coupling and reuse of components (for example, if one is bound in template A, bindtap="myclick"and the same is bound in template B bindtap="myclick", it will affect the same page events and data)

All the business and functions of the WePY component are implemented in the component itself, and the components are isolated from each other (in the above example, in the component development process of WePY, component A only affects what is bound to A myclick, and so does 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, support for native components is available in the experimental version of 1.7.2-alpha4

a. Reference components

Pages can introduce components, and components can also introduce subcomponents

/**
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>

②Circular rendering component ( new in 1.4.6 )

In WePY 1.x versions, when rendering WePY components in a loop (similar to wx:forrendering native wxml tags through loops), auxiliary tags defined by WePY must be used<repeat>

WePY components are statically compiled components (compiled into the page during the compilation phase), each component is a unique instance, and currently only provides simple  repeat support (does not support the  repeat use of components  props, ,  computedwatch etc.), so as follows:

<!-- 错误使用 --->
// 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 pass value

Props value transfer belongs to a mechanism of value transfer between parent and child components in WePY, including static value transfer and dynamic value transfer.

The static pass value passes constant data from the parent component to the child component, so only String type can be passed .

Dynamic pass-by-value means that the parent component transmits dynamic data content to the child component, and the data of the parent and child components are completely independent and do not interfere with each other. However, you can use .syncmodifiers to achieve the effect of data binding of the parent component to the child component, and you can also set the props of the twoWay: truechild component to achieve the effect of binding the data of the child component to the parent component. If you use modifiers and add them in .syncsubcomponents , you can achieve two-way binding of data.propstwoWay: 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>

④Component communication and interaction

wepy.componentThe base class provides three methods $broadcastfor communication $emitand $invokeinteraction between components:

$broadcast

$broadcastThe event is initiated by the parent component, and all child components will receive this broadcast event unless the event is manually canceled. Event broadcast order is breadth-first search order

$emit

$emitOn the $broadcastcontrary, after a component initiates an event, all ancestor components will receive the $emitevent in turn

//子组件:
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

$invokeIt is a direct call of a page/component to a method in another component, finds the corresponding component by passing in the component path, and then calls its method.

this.$invoke('ComA', 'someMethod', 'someArgs');//在页面Page_Index中调用组件ComA的某个方法
this.$invoke('./../ComB/ComG', 'someMethod', 'someArgs');//在组件ComA中调用组件ComG的某个方法
//只能在methods中使用  在周期函数使用会报错

⑤Component custom event handler ( .userevent suffix, added in 1.4.8 )

The example is as follows ( note that if a custom event is used, the corresponding listener function in events will not be executed ):

// 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 component content distribution slot

The slot in WePY is slotused as the space-occupying label of the content distribution label, which facilitates the content distribution of the sub-component in a more flexible and convenient way by "plugging and unplugging" the content distribution label equivalent to the expansion board in the parent component.

Note that the label in the parent component must have an slotattribute, and the value is the corresponding slotname in the child component, so that the content of the parent component distributes the content in the label (even if there is no content, the default content in the child component slot will not be displayed, only Delete the corresponding content distribution label in the parent component before it can be displayed) will overwrite the default content in the corresponding slot of the child component

//首先在子组件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 mix (public js)

Mixing can separate the reusable parts between components, so that when mixing is used in a component, mixed data, events and methods can be injected into the component. There are two types of mixes:

  • Default mixin (data, components, events, custom methods), that is, the options not declared by the component will be injected into the component in the mixin object, and the options declared by the component will not be affected
  • Compatible mixing ( methodsresponding to event  applet page events), that is, first respond to the component itself to respond to the event, and then respond to the response event in the mixed object ( in contrast, Vue executes the function in the mixin first, and then executes the function of the component itself )

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);//初始化请求页面数据
  }

}

When used, it is introduced and injected into the component instance ( preferably after the data attribute, otherwise an error will be reported occasionally ), eg:

(3) page page.wpy

The Page page actually inherits from the Component component, that is, the Page is also a component. Except for extending page-specific configconfiguration and page-specific life cycle functions, other properties and methods are consistent with 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) State management store (redux)

(5) app.wpy: applet entry

app.wpyThe instance inherits from the wepy.appclass, including: config configuration object (corresponding to the native file, the file will be automatically generated app.jsonaccording to the attribute during build compilation ), globalData global data object, custom methods and attributes, and applet life cycle functions.configapp.json

In the Page page instance, you can this.$parentaccess the App instance through.

<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: the entry file of the web page

2. project.config.json applet project configuration file

1.7.0Subsequent versions will be included in the root directory project.config.json. Using 微信开发者工具--> 添加项目, 项目目录please select the project root directory to complete the automatic configuration of project information according to the configuration.

1.7.0The previously generated code package may not have a project.config.jsonfile. It is recommended to manually create the file before adding the project. project.config.jsonThe contents of the file are as follows:

{
  "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/',// 运行 npm run dev命令时,域名为https://api.a.com/dev/,运行 npm run build时域名为https://api.a.com/
    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
        }
      }
    }
  }
}

Related links: mpvue documentation , native applet documentation , official account documentation

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324277519&siteId=291194637