mixins 概念 可百度  参考 http://ask.seowhy.com/article/21007

大意和Python中的多重继承, java中的接口类似(java接口只是定义,实现需要子类自己写).

而JS中没有接口的概念, 利用对象的key遍历,并合并到子类(或者叫对象)中.

伪代码:

var  mixin = { //混入对象包含一个方法
demoFunction(){ } } ; var PageOption = { //需要继承mixin的对象 };
//内部处理mixin的逻辑
processMixins(PageOption , mixin); //最终得到的 PageOption
PageOption = {
demoFunction(){ }
};

mixins 可以有多个,遭遇名称冲突时的规则 见下图:    vue的component可以简单理解为 微信小程序的PageOption

我们的框架中,mixins的处理,集中在  utils/BasePageOptionClass 中.并且暂时内置了2个 顶层mixin对象

//全局mixins 基础库
var basePage = require("../mixins/BasePage.js");
//全局 mixins 扩展库,预留
var basePageExt = require("../mixins/BasePageExt.js");
 
处理方法:
/**
* 处理mixins
*/
function _processMixins__(actualOption){ var app = getApp();
var pageOption = actualOption.PageOption;
var mixins = pageOption.mixins||[]; mixins.unshift(basePage, basePageExt); var data={};
var methods = {};
var lifecycleMethods = {
"onLoad": [], "onReady": [], "onShow": [], "onHide": [], "onUnload": [],
"onPullDownRefresh": [], "onReachBottom": [], "onShareAppMessage": [], "onPageScroll": []
};
for (var i=0;i< mixins.length;i++){
var mixin = mixins[i];
var d = mixin.data;
if(d){
app.util.extend(data,d);
}
var keys=Object.keys(mixin);
for(key of keys){
if(key=="data")continue;
if (lifecycleMethods[key] ){ //生命周期函数
if (typeof mixin[key] =="function"){ //是函数
lifecycleMethods[key].push(mixin[key]); //先加入的mixin生命周期函数先执行
} else {//不是函数, 不在规范内, 作为属性,如果Page定义,舍弃,没有则并入
if (!actualOption[key]){ //防止mixin破坏页面定义
actualOption[key]=mixin[key];
}
}
}else{ //普通函数
actualOption[key] = mixin[key];
}
} }
//合并到Page定义的data
actualOption.PageOption.data = app.util.extend(data, actualOption.PageOption.data);
actualOption.PageOption.__lifecycleMethods = lifecycleMethods;
}

这样大致实现了 vue定义的冲突解决方案.

执行方法代码逻辑

            // mixins 生命周期函数 执行方案,总是先执行
var __lifecycleMethods = actualOption.PageOption.__lifecycleMethods || {};
var __lifecycleMethod = __lifecycleMethods[key];
var mixinsRunsReturn = false;
if (__lifecycleMethod && __lifecycleMethod.length>0){
for (let ii = 0; ii < __lifecycleMethod.length;ii++){
try{
var ret = __lifecycleMethod[ii].apply($target, arguments);
if(ret===false){ //这里预留增加了 mixin方法的返回值,如果是false,那么逻辑终止
mixinsRunsReturn = true;
break;
}
}catch(err){
console.log("执行mixin函数报错",err);
throw err;
}
}
}
if (mixinsRunsReturn){
console.log("mixin函数返回false,执行被终止");
return;
}
经过改造,原先一些定义在BasePageOptionClass中的一些方法,转移到了 /mixins/BasePage.js 中.详见代码.
 
拓展思考:
哪些逻辑方法适合写入mixin
 
目前实现的:
左划删除
顶部可滑动菜单
 
实现思路其实和 微信的template,component类似
因为mixin的特性,所有引入mixin类,就引入了支持 这些操作或者效果的代码.
wxml 直接在页面中书写, css 引入, 这个步骤 和组件的步骤是一致的.
优点是灵活.编码规则上,多增加点前缀,避免名称冲突
在良好的文档支持下,内部开发应该不成问题
 
 
/**
* 左划需要的事件
* wxss中 增加 @import "/style/modules/left_touch.wxss";
*
* 用法 Page页面增加
* let left_touch = require("../../../mixins/left_touch.js");
* PageOption 增加 mixins:[left_touch]
*
* wxml 示例
<view class='left_touch_block'>
<view class="items">
<view wx:for="{{list}}" wx:key="{{index}}" class="touch_block_item">
<view data-data_path="list[{{index}}]._txtStyle" bindtouchstart="_touchS" bindtouchmove="_touchM" bindtouchend="_touchE" data-index="{{index}}" style="{{item._txtStyle}}" class="inner touch_block_content">
<view>{{index}}</view>
<view>{{item.txt}}</view>
</view>
<view data-index="{{index}}" bindtap = "_btn_touched" class="inner touch_block_btn">删除</view>
</view>
</view>
</view> 其中 data-data_path 标志 数据的层级,用户 设置单项的_txtStyle 属性,此属性为插件内部使用,外部数据不需要初始化这个属性
_btn_touched 方法需要自己写,见下方代码示例部分,根据具体逻辑编写 本插件更多的是为了基本的排版和通用事件的编写 *
*/
var obj = { data:{
_delBtnWidth: 180 //删除按钮宽度单位(rpx)
},
onLoad: function (options) {
// 页面初始化 options为页面跳转所带来的参数
this._initEleWidth();
},
/**
* 触摸开始事件,记录 开始坐标
*/
_touchS: function (e) {
if (e.touches.length == 1) {
this.setData({
//设置触摸起始点水平方向位置
_startX: e.touches[0].clientX
});
}
},
/**
* 触摸移动中事件
* 构建简单动画, 即 删除按钮 动态展现
*/
_touchM: function (e) {
var that = this if (e.touches.length == 1) {
//手指移动时水平方向位置
var moveX = e.touches[0].clientX;
//手指起始点位置与移动期间的差值
var disX = this.data._startX - moveX;
var _delBtnWidth = this.data._delBtnWidth;
var txtStyle = "";
if (disX == 0 || disX < 0) {//如果移动距离小于等于0,文本层位置不变
txtStyle = "left:0px";
} else if (disX > 0) {//移动距离大于0,文本层left值等于手指移动距离
txtStyle = "left:-" + disX + "px";
if (disX >= _delBtnWidth) {
//控制手指移动距离最大值为删除按钮的宽度
txtStyle = "left:-" + _delBtnWidth + "px";
}
}
//获取手指触摸的是哪一项
var dataset = e.currentTarget.dataset;
var index = dataset.index; var data_path = dataset.data_path
var updateObject = {};
updateObject[data_path] = txtStyle;
this.setData(updateObject);
}
},
/**
* 触摸结束事件
* 结合触摸开始时的坐标,算出移动的距离
* 如果距离超出删除按钮的一半,那么 算是移动成功,展示全部删除按钮,否则 删除按钮隐藏
* 注意 更新数据方式,并不是网上示例的全部数据更新
*/
_touchE: function (e) {
var self= this;
if (e.changedTouches.length == 1) {
//手指移动结束后水平位置
var endX = e.changedTouches[0].clientX;
//触摸开始与结束,手指移动的距离
var disX = this.data._startX - endX;
var _delBtnWidth = this.data._delBtnWidth;
var index = e.currentTarget.dataset.index; var data_path = e.currentTarget.dataset.data_path;
var updateObject = {};
//如果距离小于删除按钮的1/2,不显示删除按钮
var txtStyle = "left:0px";
if( disX > _delBtnWidth / 2 ){
txtStyle = "left:-" + _delBtnWidth + "px"
if (self._lastMovedElePath) {
updateObject[self._lastMovedElePath] = "left:0px";
}
self._lastMovedElePath = data_path
} else{ }
//获取手指触摸的是哪一项 updateObject[data_path] = txtStyle; //更新列表的状态
this.setData(updateObject);
}
},
//获取元素自适应后的实际宽度
_getEleWidth: function (w) {
var real = 0;
try {
var res = wx.getSystemInfoSync().windowWidth;
var scale = (750 / 2) / (w / 2);//以宽度750px设计稿做宽度的自适应
// console.log(scale);
real = Math.floor(res / scale);
return real;
} catch (e) {
return false;
// Do something when catch error
}
},
_initEleWidth: function () {
var _delBtnWidth = this._getEleWidth(this.data._delBtnWidth);
this.setData({
_delBtnWidth: _delBtnWidth
});
},
/**
* 点击删除按钮事件
* 这是个示例方法,请在具体的页面Page中重写此方法逻辑
*/
_btn_touched: function (e) {
var that = this
wx.showModal({
title: '提示',
content: '是否删除?',
success: function (res) {
if (res.confirm) {
//获取列表中要删除项的下标
var index = e.target.dataset.index; // var list = that.data.list;
// //移除列表中下标为index的项
// list.splice(index, 1);
// //更新列表的状态
// that.setData({
// list: list
// });
} else {
//做页面重新渲染,或什么都不做
}
}
}) } };
module.exports= obj;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

微信小程序 - mixins的更多相关文章

  1. Vue Mixin 与微信小程序 Mixins 应用

    什么是Mixin(混入) Mixin是一种思想,用来实现代码高度可复用性,可以针对属性复制实现代码复用的想法进行一个扩展,就是混入(mixin).混入并不是复制一个完整的对象,而是从多个对象中复制出任 ...

  2. 微信小程序开发库grace vs wepy

    grace和wepy都是辅助小程序开发的开源库,本文对两者做个对比. 注:本文是作者本人的一些拙见,纯粹的技术讨论,不想引起技术信仰之争,欢迎积极.正向的讨论及建议. 如果你还不了解Grace, 请参 ...

  3. 小程序开发过程中常见问题[微信小程序、支付宝小程序]

    目录 一.样式中如何使用background-image呢? 二.使用自适应单位rpx类似于rem,布局尽量使用flex布局 三.万能的{{双大括号,用于在模版中输出变量 四.你想要的基础组件和API ...

  4. 微信小程序组件化实践

    Do Not Repeat Yourself 如何提高代码质量,方法有许多:抽象.模块.组件化,我认为它们的中心点都是--Do Not Repeat Yourself. 小程序组件化 我们先看看小程序 ...

  5. 微信小程序开发中的二三事之网易云信IMSDK DEMO

    本文由作者邹永胜授权网易云社区发布. 简介 为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程.用产品的话说就是: 云信 IM 小程序 SDK 的能力 ...

  6. 微信小程序 - toptip效果

    在Page顶部下滑一个提示条 , 代码见 /mixins/UIComponent.js ,其中的self 可以认为是微信小程序的Page对象 效果: 默认2秒展示,上移动画隐藏 /** * 展示顶部 ...

  7. 微信小程序项目转换为uni-app项目

    一.它是谁? [miniprogram-to-uniapp]转换微信小程序"项目为uni-app项目.原则上混淆过的项目,也可以进转换,因为关键字丢失,不一定会完美. 二.它的原理是什么? ...

  8. 微信小程序开发心得

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...

  9. 微信小程序体验(2):驴妈妈景区门票即买即游

    驴妈妈因为出色的运营能力,被腾讯选为首批小程序内测单位.驴妈妈的技术开发团队在很短的时间内完成了开发任务,并积极参与到张小龙团队的内测问题反馈.驴妈妈认为,移动互联网时代,微信是巨大的流量入口,也是旅 ...

随机推荐

  1. 【php】Apache无法自己主动跳转却显示文件夹与php无法连接mysql数据库的解决方式

    一.Apache无法自己主动跳转却显示文件夹 Apache无法自己主动跳转却显示文件夹这是由于Apacheserver下conf/httpd.conf没有配置好,其默认是不跳转,直接显示文件夹 首先, ...

  2. 【ichartjs】用ichartjs替代Excel做直方图

    在 http://www.cnblogs.com/xiandedanteng/p/8717506.html 一文中,最后是用Excel作图,现在用ichartjs替代之. 效果如下: 文件下载: ht ...

  3. C#基础视频教程7.2 如何编写简单游戏

    前面一小节我们实现了简单的碰撞检测,但是实际上游戏的对象并不是一个标准的矩形(小鸟是一个不规则的物体,其实碰撞的管道也是不规则物体),所以如果真的要做的比较完美,我们自己要写一个方法,能够导入一个图像 ...

  4. 说说PHP中的命名空间相关概念

    说说PHP中的命名空间相关概念 1. PHP中的命名空间是什么? 什么是命名空间?"从广义上来说,命名空间是一种封装事物的方法.在非常多地方都能够见到这样的抽象概念. 比如.在操作系统中文件 ...

  5. Java之JVM调优案例分析与实战(4) - 外部命令导致系统缓慢

    环境:这是一个来自网络的案例:一个数字校园应用系统,运行在一台4个CPU的Solaris 10操作系统上,中间件为ClassFish服务器.系统在进行大并发压力测试的时候,发现请求响应时间比较慢,通过 ...

  6. eclipse maven Cannot change version of project facet Dynamic web module to 3.0

      eclipse maven Cannot change version of project facet Dynamic web module to 3.0 (eclipse 修改maven项目的 ...

  7. 【Oracle】Oracle常用语句集合

    表相关 1.快速统计大表记录数 select table_name, t.num_rows, t.last_analyzed  from tabs t WHERE table_name='TABLE_ ...

  8. EL函数库

    一.EL函数库介绍 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用. 这些EL函数在JSTL开发包中进行描述,因此在JSP页 ...

  9. Android Studio集成SVN报错:can&#39;t use subversion command line client : svn

    Android Studio集成SVN插件,check out出代码后.每次开启都会在右上角出现例如以下错误: Can't use Subversion command line client: sv ...

  10. ios开发-Object-C可变参数函数

    简介 一个可变参数函数是指一个函数拥有不定的参数,即为一个函数可接收多个参数.有时我们会遇到一些算术问题需要用到,比如是计算传入参数的总和,字符串的连接或是其它操作过程,我们在 OC 里也经常使用,最 ...