avalon代码复用研究
使用avalon开发已经有小半年了,从一个刚接触JavaScript的小菜成长到可以较熟悉的使用avalon处理业务逻辑,还是比较庆幸有这么好的国人写的前端框架。但是在用的过程中还是有些地方不够如意,和同事探讨关于avalon代码复用的问题,其中提到了很多方法,包括使用ms-include写成模板文件并配套封装好的VM等,还是可以解决问题的,不过这样不就违背了分离的思想了吗?之后听到同事提到angular有service的概念,所以就准备开始学学angular,简单的学习和思考后将angular的依赖注入借鉴过来,所以有了今天的博客。仅仅是拙见,欢迎指正。
废话不多说,上干货
中心思想:在笔者看来avalon.vmodels 就相当于一个avalon vm的容器我们只有获取通过id获取vm再将其设为另一个vm的属性就完成依赖注入,就是这么简单。(类似spring的ApplicationContext通过bean Id获取bean实例,其实angular的作者就是从后台转到前端,思维有点影响吧)
基础功能代码 avalon-inject.js这里写图片描述
/**
* avalonContainer:avalon VM容器,提供注入VM间的依赖的功能
* 例:vm1 注入vm2(id:'service')的依赖后,vm1将拥有一个名为 "$service"的属性,持有vm2的引用
*/
var avalonContainer = (function () {
var doInject = function ($vm, injections) {
for (var i = 0; i < injections.length; i++) {
//注入依赖
$vm['$' + injections[i]] = avalon.vmodels[injections[i]];
}
};
/**
* 共有方法:注入依赖函数,两种调用方式
* 1:avalonContainer.inject(id, injections)
* => id: avalon VM的$id值,此时id必须是已经通过avalon.define的VM的id
* => injections: 数组类型,元素为被注入的avalon VM的id
* 2:avalonContainer.inject(id, injections, vmObj)
* => id: avalon VM的$id值
* => injections: 参见第1种
* => vmObj: vm对象的定义,风格同avalon.define的参数
*/
var inject = function () {
var $vm;
if (arguments.length == 2) {
if (($vm = avalon.vmodels[arguments[0]])) {
doInject($vm, arguments[1]);
}
} else if (arguments.length == 3) {
$vm = arguments[2];
$vm.$id = arguments[0];
doInject($vm, arguments[1]);
return avalon.define($vm);
}
};
return {
inject: inject
};
})();
业务逻辑代码 avalonInjectTest.js
avalon.ready(function () {
/*
在这里可以定义通用层的私有方法
*/
//将通用性的代码抽出来,定义成一个vm,对外暴露接口方法
//定义vm,一般处理和后台的数据交互,并将数据整合好交给Controller
avalon.define({
$id:'userService',
getAllUser:function (callback) {
$.getJSON('../mock/users.json', function (data) {
//在这里可以对数据进行简单处理使之能够直接交给Controller从而便于View展现
callback && callback(data);
});
}
});
//ContrllerVM
var userCtrlVM = avalonContainer.inject('userCtrl', ['userService'], {
users:[],
findUsers:function () {
//调用服务层方法,应该都是封装好了的,不需要进行过多的逻辑处理
userCtrlVM.$userService.getAllUser(function (data) {
userCtrlVM.users = data;
});
}
});
avalon.scan(document.getElementById('userCtrl'), userCtrlVM);
userCtrlVM.findUsers();
});
页面做个简单展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>avalonInject</title>
<script typet="text/javascript" src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="libs/avalon1.5.8.js"></script>
<script type="text/javascript" src="js/avalon/avalon-inject.js"></script>
<script type="text/javascript" src="js/avalon/avalonInjectTest.js"></script>
</head>
<body ms-controller="userCtrl" id="userCtrl">
<div>
<ul>
<li ms-repeat="users">
<span>{{el.name}}</span>
</li>
</ul>
</div>
</body>
</html>
结果截屏
至此已经结束了,就是很简单代码复用,主要使用了avalon.vmodels对象。性能容错什么的都没考虑,只是自己瞎想,仅供参考,欢迎指正交流。