H***@qq.com
H***@qq.com
  • 发布:2017-12-20 20:53
  • 更新:2017-12-20 20:53
  • 阅读:3732

Mui vue slider

分类:HTML5+

如果你在开发中看见有这种类型的页面


你一定会记得在Mui的MuiDemo中有一个这样的页面

哇!
这不就是一样的么!!!!!!
于是屁颠屁颠的开工搞起了
心里想着今天又是愉快的一天 这个demo真的是好
是真的开心!
然而不管你用上面数据模版结合这个使用的时候你会发现
这个页面做出来是不能滑的

LZ用的是VUE(感觉有点像我的性格 小清新简单强大)

于是想办法
打断点 然而你会发现这种情况有点无从下手
决定是你了 于是开始百度大法了
LZ试过N种百度问法

解说大多数都是说:

$nextTick(function () {  
          var sliderMuiObj = mui("#slider");  
                sliderMuiObj.slider({  
                    interval: 3000  
                });  
})

然而上面的方法并没有什么卵用

好了 直接讲解决办法

1.上面的代码写到数据更新以后

  1. 在title标签下面添加<script src="html5plus://ready"></script>
  2. 把mui.plusReady(function () {})里面的方法写到外面 然后重新运行代码

然后可以惊奇的发现可以滑动了!!!!!!!!

当你解决一个问题的时候如果能够知道原理 那才是最有用的东西
那么我们来分析一下原理

首先数据绑定有三种方式:
发布者-订阅者模式(backbone.js)
脏值检查(angular.js)
数据劫持(vue.js)

三种实现双向绑定(响应式)的做法

发布者-订阅者模式(backbone.js)
脏值检查(angular.js)
数据劫持(vue.js)

  1. 发布者-订阅者模式: 一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set('property', value),这种方式现在毕竟太low了,我们更希望通过 vm.property = value 这种方式更新数据,同时自动更新视图,于是有了下面两种方式

  2. 脏值检查: angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,最简单的方式就是通过 setInterval() 定时轮询检测数据变动,当然Google不会这么low,angular只有在指定的事件触发时进入脏值检测,大致如下:

DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
XHR响应事件 ( $http )
浏览器Location变更事件 ( $location )
Timer事件( $timeout , $interval )
执行 $digest() 或 $apply()

  1. 数据劫持: vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

思路整理

已经了解到vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的,无疑这个方法是本文中最重要、最基础的内容之一,如果不熟悉defineProperty,可以去MDN上看看

整理了一下,要实现mvvm的双向绑定,就必须要实现以下几点:

1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4、mvvm入口函数,整合以上三者
这里写一个小Demo
JS部分

(function (g, nui) {g.nui = nui;})(this, function(obj){  
  this.verson = '2.5.1';  
  this.el = obj.el;  
  this.data = {};  
  this.nodes = {};  
  var _self = this  
  if(!obj.data){obj.data = {};}  
  Object.keys(obj.data).forEach(function(key){  
    defineReactive(_self.data, key, obj.data[key]);  
  });  
  function defineReactive(data, key, val) {  
    Object.defineProperty(_self.data, key, {  
      enumerable: true,  
      configurable: false,  
      get: function() {return val;},  
      set: function(newVal){  
        val = newVal;  
        var cnode = _self.nodes[key];  
        if(cnode){for(var i = 0;  i < cnode.length; i++){cnode[i].textContent = newVal;}}  
      }  
    });  
  }  
  //设置变量值  
  this.setData = function(objs){Object.keys(objs).forEach(function(k){_self.data[k] = objs[k];});}  
  this.isElementNode = function(node) {return node.nodeType == 1;}  
  this.isTextNode = function(node){return node.nodeType == 3;}  
  this.compileText = function(node, varName){  
    var varName = varName.substring(2, varName.length - 2);  
    console.log(varName);  
    var value = _self.data[varName];  
    node.textContent = typeof value == 'undefined' ? '' : value;  
    if(!this.nodes[varName]){this.nodes[varName] = [];}  
    this.nodes[varName].push(node);  
  }  
  this.compileFor = function(node, varName){  
    var value = _self.data[varName];  
    if(!value){node.parentNode.removeChild(node); return false;}  
    var parentDom = node.parentNode;  
    for(var i = 0; i < value.length; i++){  
      var newNode = node.cloneNode(true);  
      newNode.removeAttribute('nui-for');  
      var html = newNode.innerHTML;  
      var newHtml = html.replace(/{{item}}/g, '{{'+varName+'['+i+']}}');  
      console.log(newHtml);  
      newNode.innerHTML = newHtml;  
      parentDom.appendChild(newNode);  
    }  
    parentDom.removeChild(node);  
    //编译列表  
    this.compileSons(parentDom);  
  }  
  this.compileSons = function(el){  
    var childNodes = el.childNodes;  
    [].slice.call(childNodes).forEach(function(node){  
      var reg = /{{.*?}}/g;  
      if (_self.isElementNode(node)){  
        _self.compileSons(node);  
      }else if (_self.isTextNode(node)){  
        var regs = node.textContent.match(reg);  
        if(regs){  
          if(regs.length == 1){_self.compileText(node, regs[0]);}else{  
            var ortherText = node.textContent.split(reg), newTextNodes = [];  
            for(var  i = 0; i < ortherText.length; i++){  
              node.parentNode.insertBefore(document.createTextNode(ortherText[i]), node);  
              if(regs[i]){  
                var cnode = document.createTextNode(regs[i]);  
                node.parentNode.insertBefore(cnode, node);  
                _self.compileText(cnode, regs[i]);  
              }  
            }  
            node.parentNode.removeChild(node);  
          }  
        }  
      }  
    });  
  }  
  this.compile = function () {  
    this.els = document.querySelector(this.el);  
    if(this.els  == null){return ;}  
    this.fragment = document.createDocumentFragment();  
    var child;  
    while(child = this.els.firstChild){this.fragment.appendChild(child);}  
    this.compileSons(this.fragment);  
    this.els.appendChild(this.fragment);  
  }  
  this.compile();  
});

html 部分

<!DOCTYPE html>  
<html>  
<head>  
<meta charset="UTF-8">  
<title></title>  
</head>  
<body>  

  {{myname}}...{{test}}123..<br />  
  {{age}}...  

<span>{{test}}</span>  

  <button onclick="t();">test</button>  

<script type="text/javascript" src="common.js"></script>  
<script type="text/javascript">  
var app = new nui({  
  el : "body",  
  data : {  
    myname : 'name',  
    age : 18,  
    test : 'test'  
  }  
});  
function t(){  
  app.setData({myname : 'name new ', test:'test new'});    
}  
</script>  
</body>  
</html>

滑动不了的原因是因为html部分代码是在plusReady环境之前运行
我们引入以后第二个步骤就是为了让所有的代码在plusReady之后执行
这样就不会引起阻塞这样就可以完美运行了
如果你够幸运开始就看见我的这篇又可以屁颠屁颠的开搞了!!!

可能由于我学识浅薄,导致您发现有严重谬误的地方,请一定在评论中指出,我会在第一时间修正我的博文,以避免误人子弟。

2 关注 分享
BoredApe 1***@qq.com

要回复文章请先登录注册

java屌丝

java屌丝

http://ask.dcloud.net.cn/m/question/50983
2017-12-21 04:07
java屌丝

java屌丝

牛逼,看不太懂....高手对vue这么通能帮忙看下我这个问题吗?
2017-12-21 04:06