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. [ES6] 02. Traceur compiler and Grunt

    Local Install:  npm install -g traceur npm install grunt-contrib-watch npm install grunt-traceur-lat ...

  2. TCP/IP具体解释学习笔记——地址解析协议ARP

    一 概述 我们知道,IP协议是用来在不同的物理网络之间数据传输的.要在不同的网络之间数据传输,至少须要将IP协议所用的地址转换成特定网络所使用的物理地址. 一般来说.就是将IPv4地址转换为mac地址 ...

  3. Project has no project.properties file! Edit the project properties to set one.

    解决办法: 右击项目,选择android tools-->fix project properties.然后重启eclipse即可.

  4. Asp.Net Web Api 图片上传

    public string UploadFile()        {            if (Request.Content.IsMimeMultipartContent())         ...

  5. Java中解压文件名有中文的rar包出现乱码问题的解决

    import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...

  6. 算法笔记_044:表达式计算求值(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的 ...

  7. 使用SimHash进行海量文本去重

    阅读目录 1. SimHash与传统hash函数的区别 2. SimHash算法思想 3. SimHash流程实现 4. SimHash签名距离计算 5. SimHash存储和索引 6. SimHas ...

  8. SQL server 2008里面通过sys.dm_exec_procedure_stats得到存储过程的执行信息--转

    --转自:http://blogs.msdn.com/b/apgcdsd/archive/2011/05/13/sql-server-2008-sys-dm-exec-procedure-stats. ...

  9. git——分布式版本控制系统

    Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件 ...

  10. adb--monkey 压力测试工

    android压力测试命令monkey详解 http://www.jb51.net/article/48557.htm 作者: 字体:[增加 减小] 类型:转载 这篇文章主要介绍了android mo ...