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. Servlet对文件的读写操作

    (1)怎样在serlvet中读取文件的内容 package com.tsinghua; import java.io.*; import javax.servlet.http.*; public cl ...

  2. 10个CSS简写技巧让你永远受用

    转自:http://blog.bingo929.com/10-css-shorthand-tips.html 前言: CSS简写就是指将多行的CSS属性声明化成一行,又称为CSS代码优化.CSS简写的 ...

  3. [OpenGL红宝书]第一章 OpenGL概述

    第一章 OpenGL概述 标签(空格分隔): OpenGL 第一章 OpenGL概述 1 什么是OpenGL 2 初识OpenGL程序 3 OpenGL语法 4 OpenGL渲染管线 41 准备向Op ...

  4. C#应用视频教程1.3 Socket通信客户端完善

    我们先把前面的代码封装成一个完整的类,因为跟网络相关的方法并不一定是建立socket的服务器和客户端,所以还是应该把两个分开,比如获取本机IP,修改本机IP,PING远程主机这些事情应该放在一个单独的 ...

  5. windows下基于apache的SVN启动失败修改

    我用的svn版本是:Setup-Subversion-1.8.1-1.msi, Apache版本是httpd-2.2.25-win32-x86-no_ssl.msi,安装完后把SVN bin文件夹下的 ...

  6. 转 SqlServer中如何实现自动备份数据!

    第1种方法: 企业管理器  --管理  --右键数据库维护计划  --新建维护计划  --<下一步>  --选择你要备份的数据库  --<下一步>直到"指定数据库备份 ...

  7. qs.js库 使用方法

    1.qs.js库说明 qs是一个url参数转化(parse和stringify)的js库. https://www.npmjs.com/package/qs 2.使用(以vue文件做示例) (1)基本 ...

  8. pdf+iphone+wechat

    可能很多人要问,为啥标题取这个名字. 因为今天在这个上面踩了太多坑.. 我们的需求其实很简单.做一个页面,把pdf文档嵌进去,在线显示. 如此需求,放在PC上chrome浏览器,一个embed标签就搞 ...

  9. Spring+Struts+Hibernate 简介(转)

    http://blog.csdn.net/slnqnd/article/details/1772910/ Struts2.0 +Hibernate 3.2 +Spring 2.0 一.         ...

  10. OFBiz:初始RequestHandler

    RequestHandler,可以称之为请求处理器,在ControlServlet.init()中初始化: public class ControlServlet extends HttpServle ...