이 글은 주로 믹스인 확장에 대한 위챗 애플릿 개발 튜토리얼을 소개하고 있습니다. 이제 공유합니다. 필요한 친구들이 참고할 수 있습니다.
믹스인은 부분적으로 구현된 코드를 사용하는 아이디어입니다. 재사용. 다중 상속 문제를 해결하는 데 사용할 수 있으며 기능을 확장하는 데 사용할 수 있습니다. 다음 글에서는 위챗 미니 프로그램에 믹스인 확장 기능을 추가하는 방법에 대해 주로 소개합니다. 필요한 친구들이 참고하면 됩니다.
Mixin 소개
Mixin(weaving) 패턴은 GOF의 "디자인 패턴" 요약에 포함되어 있지 않지만, 이 패턴(또는 아이디어)의 일부 응용 프로그램은 다양한 언어와 프레임워크에서 찾을 수 있습니다. 간단히 말해서 Mixin은 전체 또는 부분 구현이 가능한 인터페이스이며 주요 기능은 더 나은 코드 재사용입니다.
Mixin의 개념은 React 및 Vue에서 지원되며 비즈니스 로직을 추상화하고 코드 재사용에 편리함을 제공합니다. 그러나 네이티브 미니 프로그램 프레임워크는 Mixin을 직접 지원하지 않습니다. 먼저 매우 실용적인 요구 사항을 살펴보겠습니다.
모든 미니 프로그램 페이지에 실행 환경 클래스를 추가하면 일부 스타일 해킹을 더 쉽게 할 수 있습니다. 구체적으로, 미니 프로그램이 서로 다른 운영 환경(Developer Tools | iOS | Android)에서 실행될 때 플랫폼 값은 해당 운영 환경 값("ios | android | devtools")이 됩니다.
<view class="{{platform}}"> <!--页面模板--> </view>
에서 믹스인 사용을 검토하세요. vue
글 시작 부분에서 언급한 문제는 Mixin을 사용하여 해결하기에 매우 적합합니다. 우리는 이 요구 사항을 Vue 문제로 전환했습니다. 즉, 각 라우팅 페이지에 플랫폼 스타일 클래스를 추가했습니다(비록 실용적이지 않을 수도 있음). 구현 아이디어는 각 라우팅 구성요소에 data: platform
을 추가하는 것입니다. 코드는 다음과 같이 구현됩니다. data: platform
。代码实现如下:
// mixins/platform.js const getPlatform = () => { // 具体实现略,这里mock返回'ios' return 'ios'; }; export default { data() { return { platform: getPlatform() } } }
// 在路由组件中使用 // views/index.vue import platform from 'mixins/platform'; export default { mixins: [platform], // ... }
// 在路由组件中使用 // views/detail.vue import platform from 'mixins/platform'; export default { mixins: [platform], // ... }
这样,在index,detail两个路由页的viewModel上就都有platform这个值,可以直接在模板中使用。
vue中mixin分类
data mixin
normal method mixin
lifecycle method mixin
用代码表示的话,就如:
export default { data () { return { platform: 'ios' } }, methods: { sayHello () { console.log(`hello!`) } }, created () { console.log(`lifecycle3`) } }
vue中mixin合并,执行策略
如果mixin间出现了重复,这些mixin会有具体的合并,执行策略。如下图:
如何让小程序支持mixin
在前面,我们回顾了vue中mixin的相关知识。现在我们要让小程序也支持mixin,实现vue中一样的mixin功能。
实现思路
我们先看一下官方的小程序页面注册方式:
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: 'MINA' } })
假如我们加入mixin配置,上面的官方注册方式会变成:
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: 'MINA' } })
这里有两个点,我们要特别注意:
Page(configObj)
- 通过configObj配置小程序页面的data, method, lifecycle等
onLoad方法 - 页面main入口
要想让mixin中的定义有效,就要在configObj正式传给Page()
之前做文章。其实Page(configObj)
就是一个普通的函数调用,我们加个中间方法:
Page(createPage(configObj))
在createPage这个方法中,我们可以预处理configObj中的mixin,把其中的配置按正确的方式合并到configObj上,最后交给Page()
/** * 为每个页面提供mixin,page invoke桥接 */ const isArray = v => Array.isArray(v); const isFunction = v => typeof v === 'function'; 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 = ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage']; const APP_EVENT = ['onLaunch', 'onShow', 'onHide', 'onError']; 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 === 'onLoad') return; ret[key] = methods[key]; } }); // 提取lifecycle PAGE_EVENT.forEach(key => { if (isFunction(mixin[key]) && key !== 'onLoad') { 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; };
Page(createPage(configObj))rrreee이런 방식으로 두 라우팅 페이지인 index와 Detail의 viewModel은 템플릿에서 직접 사용할 수 있는 플랫폼 값을 갖습니다.
vue
코드로 표현하면 다음과 같습니다:
rrreeemixin merge in vue, 실행 전략
먼저 공식 미니 프로그램 페이지 등록 방법을 살펴보겠습니다: rrreeemixin 구성을 추가하면 위 공식 등록 방법은 다음과 같습니다:
rrreee🎜🎜여기서 특별히 주의해야 할 두 가지 사항이 있습니다. 🎜🎜🎜Page(configObj)
- 구성 configObj를 통한 애플릿 페이지의 데이터, 메소드, 라이프사이클 등🎜Page(configObj)
는 일반적인 함수 호출입니다. 중간 메서드를 추가합니다: 🎜rrreee🎜 createPage 메서드에서는 configObj에서 믹스인을 전처리하고 올바른 구성을 누를 수 있습니다. 메서드가 병합됩니다. configObj에 넣고 마지막으로 Page()
에 넘겨졌습니다. 이것이 믹스인을 구현하는 아이디어이다. 🎜🎜🎜🎜특정 구현🎜🎜🎜🎜구체적인 코드 구현은 자세히 설명하지 않습니다. 다음 코드를 볼 수 있습니다. 더 자세한 코드 구현, 추가 확장 및 테스트는 github🎜rrreee🎜🎜Summary🎜🎜🎜🎜1을 참조하세요. 이 글에서는 주로 작은 프로그램에 믹스인 지원을 추가하는 방법에 대해 설명합니다. 구현 아이디어는 다음과 같습니다: configObj🎜rrreee🎜2. 믹스인 중복을 처리할 때 vue와 일치해야 합니다. 🎜🎜 데이터, 메서드가 병합되고 구성 요소 자체가 가장 높은 우선 순위를 가지며 믹스인에서 나중에 구성된 믹스인은 더 높은 우선순위. 🎜🎜🎜 수명 주기는 병합되지 않습니다. 먼저 믹스인의 수명주기를 순차적으로 실행한 다음 구성 요소 자체의 수명주기를 실행합니다. 🎜🎜위 내용은 이 글의 전체 내용입니다. 모든 분들의 학습에 도움이 되었으면 좋겠습니다. 더 많은 관련 내용은 PHP 중국어 홈페이지를 주목해주세요! 🎜🎜관련 권장 사항: 🎜🎜🎜WeChat 애플릿에서 페이지로 이동하는 두 가지 방법🎜🎜🎜🎜🎜탭 효과를 달성하기 위해 WeChat 개발을 위한 JS🎜🎜🎜🎜🎜🎜🎜위 내용은 WeChat Mini 프로그램 개발 튜토리얼: 믹스인 확장 추가의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!