MVVM模式
MVVM模式是 为视图层(View)定制一套视图模型(ViewModel),并在设图模型(ViewModel)中创建属性和方法,为视图层(View)绑定数据(Model)并实现交互的一种设计模式,通过数据模型层(Model)来控制视图层(View)的显示效果。
VM是MVVM模式的核心,最重要的就是对于VM层逻辑的处理,数据模型层可以自由修改,因而达到改变视图层显示效果的目的
示例:创建一个滑动条组件
V层:
<div class="first" data-bind="type: 'slider', data: demo1 "></div>
<div class="second" data-bind="type: 'slider', data: demo2 "></div>
<div class="third" data-bind="type: 'progressbar', data: demo3 "></div>
VM层:
1、获取全局变量window
2、获取页面body元素中字号作为创建页面UI组件的参考尺寸
3、将视图模型(VM)层对象绑定在window上供外部操作
var VM = function() {
//组件创建策略对象,日后需要增加其他组件只需要在策略对象中添加创建组件的方法就可以了
var Method = {
//进度条组件
/**
*进度条组件创建方法
*dom 进度条容器
* data 进度条数据模型
**/
progressbar : function (dom , data) {
//进度条进度完成容器
var progress = document.createElement('div'),
//数据模型数据
param = data.data;
//设置进度完成容器尺寸
progress.style.width = (param.position || 100) + '%';
//为进度条组件添加UI样式
dom.className += ' ui-progressbar'
//进度完成容器元素插入进度条容器中
dom.appendChild(progress)
} ,
//滑动条组件
/**
*滑动条组件创建方法
*dom 滑动条容器
* data 滑动条数据模型
**/
slider : function (dom , data) {
//滑动条拨片
var bar = document.createElement('span'),
//滑动条进度容器
progress = document.createElement('div'),
//滑动条容器提示信息
totleText = null,
//滑动条拨片提示信息
progressText = null,
//数据模型结构
param = data.data,
//容器元素宽度
// width = dom.clientWidth,
width = param.width,
//容器元素横坐标值
left = dom.offsetLeft,
//拨片位置(以数据模型中的position数据计算)
realWidth = (param.position || 100) * width / 100;
//清空滑动条容器,以创建滑动条
dom.innerHTML = '';
//如果模型数据中提供容器总量信息(param.totle),则创建滚动条提示文案
if(param.totle) {
//容器总量提示文案
text = document.createElement('b');
//拨片位置提示文案
progressText = document.createElement('em');
//设置容器总量提示文案
text.innerHTML = param.totle;
//将容器总量提示文案元素添加到滑动条组件中
dom.appendChild(text);
//将拨片位置提示文案元素添加到滑动条组件中
dom.appendChild(progressText);
}
//设置滑动条
setStyle(realWidth);
//为滑动条组件添加UI样式
dom.className += ' ui-slider';
//将进度容器添加到滑动条组件中
dom.appendChild(progress);
//将拨片添加到滑动条组件中
dom.appendChild(bar);
//设置滑动条样式的函数
function setStyle(w) {
//设置进度容器宽度
progress.style.width = w + 'px';
//设置拨片横坐标
bar.style.left = w - FONTSIZE / 2 + 'px';
//如果有拨片提示文案内容
if(progressText) {
//设置拨片提示文案横坐标
// progressText.style.left = w - FONTSIZE / 2 * 24 + 'px';
//设置拨片提示文案内容
progressText.innerHTML = parseFloat(w / width * 100).toFixed(2) + '%'
}
}
//使滑动条动起来的函数
//按下鼠标拨片
bar.onmousedown = function(){
//移动拨片(鼠标光标在页面中滑动,事件绑定给document可以优化交互体验,使鼠标光标可以在页面中自由滑动)
document.onmousemove = function (event) {
//获取事件源
var ev = event || window.event;
//鼠标光标相对于滑动条容器位置原点移动的横坐标
var w = ev.clientX - left;
//设置滑动条
setStyle(w < width ? (w > 0 ? w : 0) : width);
}
//阻止页面滑动选取事件
document.onselectstart = function () {
return false;
}
}
//停止滑动交互(鼠标按键松开)
document.onmouseup = function() {
//取消document鼠标光标移动事件
document.onmousemove = null;
//取消document滑动选取事件
document.onselecestart = null;
}
}
}
/***
* 获取视图层组件渲染数据的映射信息
* dom 组件元素
***/
function getBindData(dom) {
//获取组件自定义属性data-bind值
var data = dom.getAttribute('data-bind');
//将自定义属性data-bind值转化为对象
return !!data && (new Function("return ({" + data + "})")) ();
}
//组件实例化方法
return function () {
//获取页面所有元素
var doms = document.body.getElementsByTagName('*'),
//元素自定义数据句柄
ctx = null;
//UI处理是会向页面中插入元素,此时doms.length会改变,此时动态获取doms.length
for ( let i = 0 ; i < doms.length ; i++){
//获取元素自定义数据
ctx = getBindData(doms[i]);
//如果元素是UI组件,则根据自定义属性中组件类型,渲染该组件
ctx.type && Method[ctx.type] && Method[ctx.type](doms[i] , ctx);
}
}
}();
Model层
var demo1 = {
position: 20,
totle : 200,
width : 500
},
demo2 = {
position : 30,
width : 500
},
demo3 = {
position : 30
}
最后调用函数
window.onload = function () {
VM()
}
CSS样式
<style>
.ui-progressbar{
width:500px;
height:20px;
border:1px solid #ccc;
border-radius:4px;
}
.ui-slider{
width:500px;
height:20px;
background:#666;
margin:20px 0;
border:1px solid #ccc;
border-radius:4px;
position:relative;
}
.ui-slider>div{
height:100%;
background:#bfa;
position:absolute;
top:0;
}
.ui-slider>span{
width:16px;
height:24px;
background:#ccc;
position:absolute;
top:-2px;
border-radius:6px;
}
.ui-slider>em{
position:absolute;
left:100%;
margin-left:60px;
}
.ui-slider>b{
position:absolute;
left:100%;
margin-left: 20px;
}
.ui-progressbar> div{
height:100%;
background:#bfa;
}
</style>
最后看下实现效果