Wepy document: https://tencent.github.io/wepy/

Install Weby globally: NPM i-g Weby-cli

Initialize the project: wepy init standard myproject

Switch to the project directory: CD myproject

Installation dependency: NPM install

Weby project directory

├─ Bass Exercises ─ Components // Component Directions │ ├─ Bass Exercises ─ Mixins // General Functions │ ├─ Mocks // │ ├─ Bass Exercises – – Pages // Bass Exercises – – App.wpy // Bass Exercises – – Index.html // Template File Bass Exercises – wepy.config.js // Configuration file

Important reminder

  1. Use the WeChat developer tool -> to add a project. Select the dist directory for the project directory.
  2. WeChat Developer Tools –> Project –> Turn ES6 to ES5. Important: omitting this item will cause an error.
  3. WeChat Developer Tools –> Projects –> Styles are automatically completed when uploading code is closed. Important: omitting this item will cause an error in some cases.
  4. WeChat Developer Tools –> Projects –> turns off code compression uploads. Important: This disable properties such as computed, props. Sync on the real machine. (Note: The compression function can be replaced by the build directive provided by WEPY. See the related introduction below and wepy.config.js and package.json files in the root directory of the Demo project.)
  5. Run NPM run dev (wepy build –watch) in the local project root to enable real-time compilation. (Note: if at the same time in the WeChat developer tool -> Settings -> editor checked the automatic compilation of small program when the file is saved, will be able to real-time preview, very convenient)

Development is introduced

Index.template.html: This is the module file

Among them through
wepy.appCreate the entry file,
wepy.pageCreate a page file,
wepy.componentCreate the component file.

App.wpy: An entry file containing config, globalData, constructor, and lifecycle. Configure the route in config

  1. Config: Configure pages, window, tabBar. They are page routing configuration, page navigation bar configuration and page bottom bar configuration. Detailed configuration in the applet framework configuration
  2. GlobalData: Global parameter configuration, common parameter for multiple pages.
  3. Constructor: configuration of interceptors.
  4. Life cycle use

If async/await is needed in the page development, import ‘wepy-async-function’ should be used in app.wpy to load the module, otherwise the page will report an error after compilation and async/await cannot be used.

{pages: ['pages/main', 'pages/admin-center'], window: {backgroundTextStyle: 'light', navigationBarBackgroundColor: '#fff', navigationBarTitleText: 'WeChat', navigationBarTextStyle: 'black' }, tabBar = { color: '#AEADAD', selectedColor: '#049BFF', backgroundColor: '#fff', borderStyle: 'black', list: [{pagePath: 'pages/index', text: 'homepage ', "iconPath": "images/ico-home.png", "selectedDiconPath ": "Images/ico-home.png"}, {pagePath: 'pages/admin-center', text: 'to read ', "iconPath": "images/ico-setting.png", "selectedIconPath": "Images /ico-setting-d.png"}]}} // global parameter (easy to use in later pages) globalData = {Prizelist: [], // list of prizes to receive} // set the interceptor, Constructor () {super() intercept(this)} // page load onLaunch(res) {console.log(res)}

Properties in the wpy module

Export default class Index @extends Weby.page {customData = {} // CustomFunction (){} // OnLoad (){} // // Config = {}; // Config = {}; // Config = {}; // Configure data that exists only in the Page instance, corresponding to the native page.json file data = {}; // The template data binding component = {}; // declare the component referenced in the page, or declare the child component referenced in the component mixins = []; // declare the mixins referenced by the page computed = {}; // Watch = {}; // declare data watcher (see below) methods = {}; // Declare the event handler for the tag in the page WXML. Note that this is only used to declare bind and catch events for tags in the page WXML. Custom methods must declare events = {} in the same way that custom methods do; // Declare event handlers between components}
attribute instructions
config The page configuration object, which corresponds to the native page.json file, is similar to the config in app.wpy
components A page component list object that declares the list of components to which the page is introduced
data A page render data object that holds render data that can be used for page template binding
methods A WXML event handler object that holds functions that respond to events captured in WXML, such as bindTap and bindChange, cannot be used to declare custom methods.
events A weby component event handler object that holds the events passed between the response components via $broadcast, $emit, and $invoke
other Small program page lifecycle functions, such as onLoad, onReady, and other custom methods and properties

Custom functions in wpy should be written at the same level as methods, not in methods.

The jump to the page

The routing of the page needs to be set in the pages in the config of app.wpy, and then jump to the corresponding page through navigateTo in the page. Return this.$navigate({url:””}) in the script for weby. page. This.$parent.$navigate({url:””}) or wepy.navigateto can be used in the wepy.component.html.

wepy.navigateTo({
  url: '/pages/info'
})

Lifecycle in Weby

OnLoad, OnReady, OnShow, OnPreFetch, etc. OnReady, OnShow, OnPreFetch, etc. OnReady, OnShow, OnPreFetch are only useful in Weby. page. Wepy.component only supports onLoad, nothing else is triggered.

  1. OnLoad: Called when the page has finished loading, which is called only once per page. Passed while routing the jumpnavigateToJump,onloadIt will be re-executed. PassnavigateBackJump,onLoadWill not be re-executed.)
  2. OnShow: Called when the page is displayed.
  3. OnReady: Called when all resources in the page have finished loading.
  4. OnPreFetch: Triggered when a page jumps, used for preloading and pre-querying data.
  5. OnUnload: Triggers when the page is unloaded (with Redirectto, SwitchTab, NavigateBack, Relaunch will trigger onUnload on the current page, but NavigateTo will not).

Life cycle order: onPrefetch > onLoad > onShow > onReady.

onPrefetchThis lifecycle is extended in Weby, and its trigger needs to go through
this.$navigateAnd other Wepy encapsulated jump mode to achieve. When setting
onPrefetchAfter that, can be in
onLoadSet a variable in the
onPrefetchThe value returned in the.

Case study:

onLoad (params, data) { data.prefetch.then((list) => { this.adminMath = list.chasucccnt.data.succcnt this.recordInfo = list.adminCenter.data.challengeRecList this.heightScore = list.adminCenter.data.hs this.hadMath = List. AdminCenter. Data. Cc this. $the apply ()})} / / chasucccnt, getAdminCenter request backstage function, the returned data structure is {data: {succcnt: 0}. async onPrefetch () { let chasucccnt = await this.chasucccnt() let adminCenter = await this.getAdminCenter() return new Promise((resolve, reject) => { resolve({ chasucccnt: chasucccnt, adminCenter: adminCenter }) }) }

Props implements value transfer between child and child components

Official case:

// parent.wpy <child :title = 'parentTitle' :syncTitle.sync = 'parentTitle' :twoWayTitle = 'parentTitle'></child> // CHILD.WPY props = {// static function function (); // syncTitle: function () {parentTitle: 'p-title'); { type: String, default: 'null' }, twoWayTitle: { type: Number, default: 'nothing', twoWay: true } }; 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); // This.$parent.parentTitle = 'p-title-changed'; // This.$parent.parentTitle = 'p-title-changed'; this.$parent.$apply(); console.log(this.title); // 'c-title'; console.log(this.syncTitle); // 'p-title-changed' -- props property for. Sync modifier. When changed in the parent component, it changes the child component's same value. }

There is the above case can know
:titleThe title in the child component will not change after the change of value. When the.sync is added after the property, that is, the change of the property will cause the corresponding value in the child component to change
propsSet in the
twoWay: trueAfter that, it can realize the two-way binding of parent-child components.

Data communication between components

Weby uses three methods: $broadcast, $emit, $invoke;

  1. $broadcast: The parent component fires all child (including descendant) events.
  2. $emit: The child component fires all parent (including ancestor) events. When a custom event is set using.user in the parent component property, $emit can be used to emit the custom event and the function declared in events will not be executed. (Unlike in Vue, where the child component’s properties are set in the parent component to be fired in the child component. This is not required in WEPY, and can be triggered in a child component by setting the method in Events.
  3. $invoke: The page or child component triggers another child component event.
parent.wpy <template> <view> <children @childFun.user = 'someEvent'></children> </view> </template> <script> export default class Parent extends wepy.page{ data = { name: 'parent' } events = { 'some-event': (p1, p2, p3, $event) => {// 'Parent receive some-event children',$event.source points to the child. console.log(`${this.name} receive ${$event.name} from ${$event.source.name}`) } } onLoad () { this.$broadcast('getIndex', 1, 4) } methods = { someEvent (... P) {// output [1, 2, 3, _class]. console.log(p) } } } </script> children.wpy <script> export default class Parent extends wepy.page{ data = { name: $emit('childFun', 1, 2, 3) {// this.$emit('some-event', 1, 2, 3) // This.$emit('some-event', 1, 2, 3); 3) } events = { 'getIndex': (... P) => {console.log(p) // Output [1, 4]}}} After adding @childfun. user = 'someEvent' in the parent component, $this.$emit('childFun', 1, 2, 3) //$invoke ('childFun', 1, 2, 3) After using the import import child components, when use can be directly by enclosing $invoke (' child components, must be single quotes', 'child components method name, param1, param2, param3...) ; Send events between sub-components: this $invoke (' child components of relative path, 'child components method name, param1, param2, param3...) ; When set './' that is, the current component, '.. /' is the parent component, and so on. It can specify which component to distribute content to, but only for simple component-tree structures, and for complex structures Redux is considered.

Using $emit in a child component triggers the same event in the parent component and the ancestor component. Using $broadcast in a parent component triggers the same events in child and descendant components. Where $emit and $broadcast trigger event set in the components of the events, and $invoke trigger function and events is flat, when has passed the components in the component import components, The first parameter in $invoke can be set directly to the value in Components. When a relative path is set, the path can be determined based on the current component’s position in the entire component tree. It can specify the value to be passed to a particular component, but when the structure is complex, the path that needs to be nested is complex and difficult to maintain.

Mixins hybrid

  1. Default blending (data, components, events, custom events in modules)

When the same function or variable is set in a wepy.mixin as on the page, the function or variable on the current page takes over. The function or variable on the mixin is invalidated. Official case:

// mixin.js export default class TestMixin extends wepy.mixin { data = { foo: 'foo defined by page', bar: 'bar defined by testMix' }; methods: { tap () { console.log('mix tap'); }}}... import wepy from 'wepy'; import TestMixin from './mixins/test'; export default class Index extends wepy.page { data = { foo: 'foo defined by index' }; mixins = [TestMixin ]; onShow() { console.log(this.foo); // foo defined by index console.log(this.bar); // bar defined by testMix } }

Functions declared in a mixin can call the data and functions of the page after the mixin was introduced. This in the mixin points to the current page component.

  1. Compatible blending (life cycle)

When you set a hook function like a lifecycle in a mixin, the lifecycle in the mixin takes precedence over the function in the page.

// mixin.js export default class TestMixin extends wepy.mixin { onLoad () { console.log(2222) } } .... import wepy from 'wepy'; import TestMixin from './mixins/test'; export default class Index extends wepy.page { data = { foo: 'foo defined by index' }; mixins = [TestMixin ]; onLoad() { console.log(11111); }} The result is printed as: 2222 11111

The use of WXS to implement filters

In the project directory, create a new WXS folder and add the WXS file to the folder. The new contents are as follows:

// Exports = {filter: exports; // Exports = {filter: exports; Function (num) {if (num < 10000) {return num} else {return num = (num / 10000).

Import the filter in the page through import:

Mywxs <view>{{mywxs. Filter (mitem.playerCount)}} person </view>..... import mywxs from '@/wxs/fixed.wxs' export default class Index extends wepy.page{ ...... wxs = { mywxs: mywxs } ..... }

The imported WXS file can only be used in template, not in JS

Use of Promise and Async /await (detection of dirty data)

Async endVideo (event) {let endTime = event.timestamp let startTime = this.startTime this.videoInfo = '2131' let video = await new Promise((resolve, reject) => { recorderManager.onStop((res) => { console.log('recorder stop', res) const { tempFilePath } = res resolve(tempFilePath) }) recorderManager.stop() }) if ((endTime - startTime) > 1000) {  this.videoInfo = video this.$apply() } }

When using asynchronous functions, we need to manually call the $apply() method to trigger the dirty data check process if we need to re-render the page.

Group of forwarding

Use to realize the sharing function of WeChat applet, get each group’s independent ID. By default, there is a forward button in the popup. You can hide the forward button in the popup by using HideShareMenu.

usage

Weby. showShareMenu({withShareTicket: True}) set the interface of sharing in onShareAppMessage, and get the information of sharing group through wepy.getShareInfo in the callback function after successful sharing. The group's information is encrypted and needs to be decrypted through the background. OnShareAppMessage (res) {if (res.from === 'button') {console.log(res.target)} return {title: 'custom forward title ', path: '/pages/main', success: function(res) {let shareID = res.shareTickets[0] // wepy.getShareInfo({shareTicket: shareId, success: (data) => {var EncryptedData = data.encryptedData var iv = data.iv weby.request ({url: 'http://localhost:3000/api/decode', method: 'post', data: { appId: appId, encryptedData: encryptedData, iv: iv }, success: (info) => { console.log('info:' + info) }, fail: (info) => { console.log(info) } }) console.log(data) }, fail: (data) = bb0 {console.log(data)}}) console.log(res)}, fail: function(res) {// Console. log(res)}}}

OnShareAppMessage needs to be set in wepy.page to have effect, set in wepy.component has no effect. The path parameter set in OnShareAppMessage can be followed
? Ie = value, and then set it on the corresponding page
onLoadTo get the value to follow

WeChat small program and local interface docking, simulation request data

Express is used in the background. The code is as follows:

var express = require('express');
var app = express();
app.listen(3000, function () {
    console.log('listen:3000');
})

Set the front and back docking interface:

var router = express.Router(); var bodyParser = require('body-parser'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); router.get('/info', function (req, res) { console.log(req.query); console.log(req.body); } app.use('/ API ', router) // The foreground sends a request to '/ API /info' via Ajax

Loads the module (because the front desk can’t directly to https://api.weixin.qq.com/sns… , the domain cannot be added to the server domain of the applet) :

var request = require('request'); // Used in the '/info' interface to get the SESSION_KEY. request.get({ uri: 'https://api.weixin.qq.com/sns/jscode2session', json: true, qs: { grant_type: 'authorization_code', appid: 'applet's appid ', secret:' applet's key ', js_code: code } }, (err, response, data) => { if (response.statusCode === 200) { console.log("[openid]", data.openid) console.log("[session_key]", data.session_key) session_key = data.session_key //TODO: SESSIONID = "OPEN"; SESSIONID = "OPEN"; SESSIONID = "OPEN"; redisStore.set(sessionid, openid + session_key, 7200) res.json({ openid: data.openid, session_key: data.session_key }); } else { console.log("[error]", err) res.json(err) } })

decryption

Download the file required to decrypt in the official case, wxbizDataCrypt.js. We know from the case that there are four required parameters:

2. SESSION_KEY, 3. ENCRYTEDDATA, 4. IV (algorithm initial vector) Returns in the group information retrieved.

Introducing wxbizDataCrypt.js in app.js:

Var wxbizDataCrypt = require('./ wxbizDataCrypt ') // Router. post('/decode', function (req, req) res) { var appId = req.body.appId; var sessionKey = session_key; var encryptedData = req.body.encryptedData; var iv = req.body.iv; var pc = new WXBizDataCrypt(appId, sessionKey); var data = pc.decryptData(encryptedData , iv); res.json({data: data}); })