zoukankan      html  css  js  c++  java
  • underscore.js库的浅析

    Underscore并没有在原生的JavaScript对象原型中进行扩展,而是像jQuery一样,将数据封装在一个自定义对象中(下文称“Underscore对象”)。生成一个Underscore对象:

    <script>

      var jsData = {
          name : 'data'
      }
        // 通过_()方法将对象创建为一个Underscore对象
      var underscoreData = _(jsData);   //_就是Underscore构造函数的标识

        // underscoreData对象的原型中包含了Underscore中定义的所有方法,你可以任意使用
       
      underscoreData.value();

        // 通过value方法获取原生数据, 即jsData

    </script>

    Underscore默认使用_(下划线)来访问和创建对象,但这个名字可能不符合我们的命名规范,或容易引起命名冲突。我们可以通过noConflict()方法来改变Underscore的命名,并恢复_(下划线)变量之前的值,例如:

    <script type="text/javascript">
        var _ = '自定义变量';
    </script>
    <script type="text/javascript"  src="http://handyxuefeng.blog.163.com/blog/underscore/underscore-min.js"></script>
    <script type="text/javascript">
         
        console.log(_);  // Underscore对象
         
        var us = _.noConflict();  // 将Underscore对象重命名为us, 后面都通过us来访问和创建Underscore对象
        
        console.log(_);    // 输出"自定义变量"
    </script>

    Underscore同样支持链式操作,但你需要先调用chain()方法进行声明。

    var arr = [10, 20, 30];
    _(arr)         //新建一个Underscore对象
        .chain()    //声明我要链式操作了
        .map(function(item){ return item++; })
        .first()
        .value();

    我们可以通过mixin()方法轻松地向Underscore中扩展自定义方法,例如:

    _.mixin({
        method1: function(object) {
            // to do
        },
        method2: function(arr) {
            // to do
        },
        method3: function(fn) {
            // to do
        }
    }); 

     这些方法被追加到Underscore的原型对象中,所有创建的Underscore对象都可以使用这些方法,它们享有和其它方法同样的环境。

    Underscore提供了一个轻量级的模板解析函数,它可以帮助我们有效地组织页面结构和逻辑。handlebars也是做这个处理的。如果是简单的模板解析,Backbone里面有自带的方法,它使用的就是Underscore中的方法。handlebars处理更复杂的模板解析。举例:


    <ul id="element"></ul>     //用于显示渲染后的标签

    <script type="text/template" id="tpl">     //定义模板,将模板内容放到一个script标签中
        <% for(var i = 0; i < list.length; i++) { %>
            <% var item = list[i] %>
            <li>
                <span><%=item.firstName%> <%=item.lastName%></span>
                <span><%-item.city%></span>
            </li>
        <% } %>
    </script>
    <script type="text/javascript" src="http://handyxuefeng.blog.163.com/blog/underscore/underscore-min.js"></script>
    <script type="text/javascript">
         
        var element = $('#element'),// 获取渲染元素和模板内容
            tpl = $('#tpl').html();

        // 创建数据, 这些数据可能是你从服务器获取的
        var data = {
            list: [
                {firstName: '<a href="http://handyxuefeng.blog.163.com/blog/#">Zhang</a>', lastName: 'San', city: 'Shanghai'},
                {firstName: 'Li', lastName: 'Si', city: '<a href="http://handyxuefeng.blog.163.com/blog/#">Beijing</a>'},
                {firstName: 'Wang', lastName: 'Wu', city: 'Guangzhou'},
                {firstName: 'Zhao', lastName: 'Liu', city: 'Shenzhen'}
            ]
        }
        // 解析模板, 返回解析后的内容
        var html = _.template(tpl, data);      //把json数据解析到模板中去,并生成html字符串。
         
        element.html(html);  // 将解析后的内容填充到渲染元素
    </script> 

    • 在本例中,我们将模板内容放到一个<script>标签中,你可能已经注意到标签的type是text/template而不是text/javascript,因为它无法作为JavaScript脚本直接运行。
    • 我也建议你将模板内容放在<script>中,因为如果你将它们写在一个<div>或其它标签中,它们可能会被添加到DOM树中进行解析(即使你隐藏了这个标签也无法避免)。
    • _.template模板函数只能解析3种模板标签:
    • <%  %>:用于包含JavaScript代码,这些代码将在渲染数据时被执行。
    • <%= %>:用于输出数据,可以是一个变量、某个对象的属性、或函数调用(将输出函数的返回值)。
    • <%- %>:用于输出数据,同时会将数据中包含的HTML字符转换为实体形式(例如它会将双引号转换为&quot;形式),用于避免XSS攻击。
    • 我们经常会遇到一种情况:多次调用template方法将数据渲染到同一个模板。
    • 假设我们有一个分页列表,列表中的每一条数据都通过模板渲染,当用户进入下一页,我们会获取下一页的数据并重新渲染,实际上每次渲染的模板都是同一个,但刚才描述的template所有处理过程总会被执行。
    • 其实Underscore的template方法提供了一种更高效的调用方式,我们将上面代码中的最后两句修改为:
    • var render = _.template(tpl);     // 解析模板, 返回解析后的内容
      var html = render(data);    //填充数据
      element.html(html);  // 将解析后的内容填充到渲染元素
    • 你会发现细微的差别:我们在调用template方法时只传递了模板内容,而没有传递数据,此时template方法会解析模板内容,生成解析后的可执行JavaScript代码,并返回一个函数,而函数体就是解析后的 JavaScript,因此当我们调用该函数渲染数据时,就省去了模板解析的动作。
    • 将模板内容解析为可执行的JavaScript(解析模板标签)
    • 通过with语句将解析后的JavaScript作用域修改为我们传递的数据对象,这使我们能够直接在模板中通过变量形式访问数据对象的属性
    • 执行解析后的JavaScript(将数据填充到模板)
    • 返回执行后的结果
    • if,else语句,不需要添加大括号{}。

    最后,讲几个underscore中的方法:

      map()方法与each()方法的作用、参数相同,但它会将每次迭代函数返回的结果记录到一个新的数组并返回。

      map方法在原生的js中是存在的,each方法是重写了原生js的forEach方法,请看博客:http://www.cnblogs.com/chaojidan/p/4142338.html

      debounce()方法关注函数执行的间隔,即函数两次的调用时间不能小于指定时间。

      throttle()方法更关注函数的执行频率,即在指定频率内函数只会被调用一次。

    debounce

    形像的比喻是橡皮球。如果手指按住橡皮球不放,它就一直受力,不能反弹起来,直到松手。

    debounce 的关注点是空闲的间隔时间。

    // ajaxQuery 将在停止输入 250 毫秒后执行,如果用户一直输入(空闲的间隔时间小于250ms),那么将不会执行ajaxQuery 。

    $('#autocomplete').addEventListener('keyup',debounce(250,function() { ajaxQuery(this.value,renderUI); },true))

    主要的应用场景:文本输入keydown 事件,keyup 事件,例如做autocomplete。

    throttle

    形像的比喻是水龙头或机枪,你可以控制它的流量或频率。

    throttle 的关注点是连续的执行间隔时间。

    // 当窗口大小改变时,以 50 毫秒一次的频率为单位执行定位函数 position。因为用户在拖动窗口时,会触发无数个resize事件,如果不做节流,它会执行无数次回调方法。因此使用节流方法,使每隔50毫秒(间隔时间),才执行回调方法。

    window.addEventListener('resize',throttle(50,position,true) );

    主要应用场景:window对象的resize和scroll 事件,mousemove鼠标移动事件

    加油!

  • 相关阅读:
    字符编码与解码详解
    【Java反射机制】用反射改进简单工厂模式设计
    数据结构
    根据 中序遍历 和 后序遍历构造树(Presentation)(C++)
    【动态规划】记忆搜索(C++)
    Linux环境下安装中山大学东校区iNode客户端
    webpack前端开发环境搭建
    CSS中line-height继承问题
    MySQL中MyISAM与InnoDB的主要区别对比
    JavaScript中易混淆的DOM属性及方法对比
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4156002.html
Copyright © 2011-2022 走看看