Home  >  Article  >  WeChat Applet  >  WeChat Mini Program Development Tutorial: Adding Mixin Extensions

WeChat Mini Program Development Tutorial: Adding Mixin Extensions

不言
不言Original
2018-06-23 09:37:022019browse

This article mainly introduces the WeChat mini program development tutorial on adding mixin extensions. It has a certain reference value. Now I share it with you. Friends in need can refer to it.

Mixin is a kind of thought. Use partially implemented interfaces to achieve code reuse. It can be used to solve the problem of multiple inheritance and can be used to extend functions. The following article mainly introduces you to the relevant information about adding mixin extensions to WeChat mini programs. Friends who need it can refer to it. Let’s take a look together.

Introduction to Mixin

Mixin (weaving) mode is not one of GOF’s “Design Patterns” summary, but it is used in various Languages ​​and frameworks will find some application of this pattern (or idea). Simply put, Mixin is an interface with full or partial implementation, and its main function is better code reuse.

The concept of Mixin is supported in React and Vue. It provides convenience for us to abstract business logic and code reuse. However, the native mini program framework does not directly support Mixin. Let’s first look at a very practical requirement:

Add a running environment class to all mini program pages to facilitate some style hacks. Specifically, when the mini program is run in different operating environments (Developer Tools|iOS|Android), the platform value is the corresponding operating environment value ("ios|android|devtools")

<view class="{{platform}}">
 <!--页面模板-->
</view>

Reviewing the use of mixin in vue

The problems mentioned at the beginning of the article are very suitable to be solved using Mixin. We converted this requirement into a Vue problem: add a platform style class to each routing page (although this may not be practical). The implementation idea is to add a data: platform to each routing component. The code is implemented as follows:

// mixins/platform.js
const getPlatform = () => {
 // 具体实现略,这里mock返回&#39;ios&#39;
 return &#39;ios&#39;;
};

export default {
 data() {
 return {
  platform: getPlatform()
 }
 }
}
// 在路由组件中使用
// views/index.vue
import platform from &#39;mixins/platform&#39;;

export default {
 mixins: [platform],
 // ...
}
// 在路由组件中使用
// views/detail.vue
import platform from &#39;mixins/platform&#39;;

export default {
 mixins: [platform],
 // ...
}

In this way, the viewModel of the index and detail routing pages has the value platform, which can be used directly in the template.

mixin classification in vue

  • data mixin

  • ##normal method mixin

  • ##lifecycle method mixin
  • If expressed in code, it would be like:
export default {
 data () {
 return {
  platform: &#39;ios&#39;
 }
 },

 methods: {
 sayHello () {
  console.log(`hello!`)
 }
 },

 created () {
 console.log(`lifecycle3`)
 }
}

vue Mixin merging and execution strategy If there are duplications between mixins, these mixins will have specific merging and execution strategies. As shown below:

How to make the applet support mixinIn front, we reviewed vue Knowledge about mixins. Now we need to make the mini program also support mixin and realize the same mixin function in vue.

Implementation ideas

Let’s first take a look at the official mini program page registration method:

Page({
 data: {
 text: "This is page data."
 },
 onLoad: function(options) {
 // Do some initialize when page load.
 },
 onReady: function() {
 // Do something when page ready.
 },
 onShow: function() {
 // Do something when page show.
 },
 onHide: function() {
 // Do something when page hide.
 },
 onUnload: function() {
 // Do something when page close.
 },
 customData: {
 hi: &#39;MINA&#39;
 }
})

If we add mixin configuration, the above official registration method It will become:

Page({
 mixins: [platform],
 data: {
 text: "This is page data."
 },
 onLoad: function(options) {
 // Do some initialize when page load.
 },
 onReady: function() {
 // Do something when page ready.
 },
 onShow: function() {
 // Do something when page show.
 },
 onHide: function() {
 // Do something when page hide.
 },
 onUnload: function() {
 // Do something when page close.
 },
 customData: {
 hi: &#39;MINA&#39;
 }
})

There are two points here, we should pay special attention to:

  • Page (configObj)

    - Configure the data, method, lifecycle, etc. of the mini program page through configObj

  • onLoad method - the main entrance of the page
  • If you want the definition in the mixin to be valid, you must make a fuss before configObj is officially passed to
Page()

. In fact, Page(configObj) is an ordinary function call. We add an intermediate method: <pre class="brush:php;toolbar:false;">Page(createPage(configObj))</pre>In the createPage method, we can preprocess the mixin in configObj and put the configuration in it. Merge it into configObj in the correct way, and finally hand it over to

Page()

. This is the idea of ​​​​implementing mixins.

Specific implementationThe specific code implementation will not be described in detail. You can see the following code. For more detailed code implementation, more extensions, and tests, please refer to github

/**
 * 为每个页面提供mixin,page invoke桥接
 */

const isArray = v => Array.isArray(v);
const isFunction = v => typeof v === &#39;function&#39;;
const noop = function () {};

// 借鉴redux https://github.com/reactjs/redux
function compose(...funcs) {
 if (funcs.length === 0) {
 return arg => arg;
 }

 if (funcs.length === 1) {
 return funcs[0];
 }

 const last = funcs[funcs.length - 1];
 const rest = funcs.slice(0, -1);
 return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args));
}


// 页面堆栈
const pagesStack = getApp().$pagesStack;

const PAGE_EVENT = [&#39;onLoad&#39;, &#39;onReady&#39;, &#39;onShow&#39;, &#39;onHide&#39;, &#39;onUnload&#39;, &#39;onPullDownRefresh&#39;, &#39;onReachBottom&#39;, &#39;onShareAppMessage&#39;];
const APP_EVENT = [&#39;onLaunch&#39;, &#39;onShow&#39;, &#39;onHide&#39;, &#39;onError&#39;];

const onLoad = function (opts) {
 // 把pageModel放入页面堆栈
 pagesStack.addPage(this);

 this.$invoke = (pagePath, methodName, ...args) => {
 pagesStack.invoke(pagePath, methodName, ...args);
 };

 this.onBeforeLoad(opts);
 this.onNativeLoad(opts);
 this.onAfterLoad(opts);
};

const getMixinData = mixins => {
 let ret = {};

 mixins.forEach(mixin => {
 let { data={} } = mixin;

 Object.keys(data).forEach(key => {
  ret[key] = data[key];
 });
 });

 return ret;
};

const getMixinMethods = mixins => {
 let ret = {};

 mixins.forEach(mixin => {
 let { methods={} } = mixin;

 // 提取methods
 Object.keys(methods).forEach(key => {
  if (isFunction(methods[key])) {
  // mixin中的onLoad方法会被丢弃
  if (key === &#39;onLoad&#39;) return;

  ret[key] = methods[key];
  }
 });

 // 提取lifecycle
 PAGE_EVENT.forEach(key => {
  if (isFunction(mixin[key]) && key !== &#39;onLoad&#39;) {
  if (ret[key]) {
   // 多个mixin有相同lifecycle时,将方法转为数组存储
   ret[key] = ret[key].concat(mixin[key]);
  } else {
   ret[key] = [mixin[key]];
  }
  }
 })
 });

 return ret;
};

/**
 * 重复冲突处理借鉴vue:
 * data, methods会合并,组件自身具有最高优先级,其次mixins中后配置的mixin优先级较高
 * lifecycle不会合并。先顺序执行mixins中的lifecycle,再执行组件自身的lifecycle
 */

const mixData = (minxinData, nativeData) => {
 Object.keys(minxinData).forEach(key => {
 // page中定义的data不会被覆盖
 if (nativeData[key] === undefined) {
  nativeData[key] = minxinData[key];
 }
 });

 return nativeData;
};

const mixMethods = (mixinMethods, pageConf) => {
 Object.keys(mixinMethods).forEach(key => {
 // lifecycle方法
 if (PAGE_EVENT.includes(key)) {
  let methodsList = mixinMethods[key];

  if (isFunction(pageConf[key])) {
  methodsList.push(pageConf[key]);
  }

  pageConf[key] = (function () {
  return function (...args) {
   compose(...methodsList.reverse().map(f => f.bind(this)))(...args);
  };
  })();
 }

 // 普通方法
 else {
  if (pageConf[key] == null) {
  pageConf[key] = mixinMethods[key];
  }
 }
 });

 return pageConf;
};

export default pageConf => {

 let {
 mixins = [],
 onBeforeLoad = noop,
 onAfterLoad = noop
 } = pageConf;

 let onNativeLoad = pageConf.onLoad || noop;
 let nativeData = pageConf.data || {};

 let minxinData = getMixinData(mixins);
 let mixinMethods = getMixinMethods(mixins);

 Object.assign(pageConf, {
 data: mixData(minxinData, nativeData),
 onLoad,
 onBeforeLoad,
 onAfterLoad,
 onNativeLoad,
 });

 pageConf = mixMethods(mixinMethods, pageConf);

 return pageConf;
};

Summary


1. This article mainly talks about how to add mixin support to small programs . The implementation idea is: preprocessing configObj

<pre class="brush:php;toolbar:false;">Page(createPage(configObj))</pre>

2. When dealing with mixin duplication, be consistent with vue:

data, methods will be merged, the component itself has the highest priority, followed by mixins The configured mixin has a higher priority.


lifecycle will not be merged. First execute the lifecycle in the mixins sequentially, and then execute the lifecycle of the component itself.

The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!

Related recommendations:

Two methods to jump to pages in WeChat mini programs


JS implementation of tabs in WeChat development Tab effect


The above is the detailed content of WeChat Mini Program Development Tutorial: Adding Mixin Extensions. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn