zoukankan      html  css  js  c++  java
  • dojo自定义Widget

    使dojo AMD规范进行widget 定义,开始的时候一直找不到自己定义的widget模块的位置,经过探索,总算有收获,我这个人有毛病,脑子里不允许有一些想不通的问题,一旦有了问题,就非常难受,心里暗自谩骂自己“你怎么笨蛋”,言归正传,关于dojo AMD规范这个网上一大堆,说起来就是按需加载,按照依赖加载,用一个define函数代替了原来的provide,require和declare函数,仔细研究,其实内容还是差不多的,可谓换汤不换药。
    现在就简单介绍下这个玩意儿。

     AMD是什么

    作为一个规范,只需定义其语法API,而不关心其实现。AMD规范简单到只有一个API,即define函数:

    define([module-name?], [array-of-dependencies?], [module-factory-or-object]);

    其中:

    ◆  module-name: 模块标识,可以省略。

    ◆  array-of-dependencies: 所依赖的模块,可以省略。

    ◆  module-factory-or-object: 模块的实现,或者一个JavaScript对象。

    从中可以看到,第一个参数和第二个参数都是可以省略的,第三个参数则是模块的具体实现本身。后面将介绍在不同的应用场景下,他们会使用不同的参数组合。

    从这个define函数AMD中的A:Asynchronous,我们也不难想到define函数具有的另外一个性质,异步性。当define函数执行时,它首先会异步的去调用第二个参数中列出的依赖模块,当所有的模块被载入完成之后,如果第三个参数是一个回调函数则执行,然后告诉系统模块可用,也就通知了依赖于自己的模块自己已经可用。如果对应到dojo1.6之前的实现,那么在功能上可以有如下对应关系:

    ◆  module-name: dojo.provide

    ◆  dependencies: dojo.require

    ◆  module-factory: dojo.declare

    不同的是,在加载依赖项时,AMD用的是异步,而dojo.require是同步。异步和同步的区别显而易见,前者不会阻塞浏览器,有更好的性能和灵活性。而对于NodeJs这样的服务器端AMD,则模块载入无需阻塞服务器进程,同样提高了性能。

    定义的模块可以返回函数也可以返回一个对象,这个要结合实际情况:

    define(function () {
    
        var privateValue = 0;
        return {
            increment: function () {
                privateValue++;
            },
    
            decrement: function () {
                privateValue--;
            },
    
            getValue: function () {
                return privateValue;
            }
        };
    });

    上面这个就是返回一个对象,当我们dojoConfig定义了这个包的位置的时候,并且使用了require函数后,就可以在代码中使用了

     var 
               dojoConfig = {
                   parseOnLoad: true,
                   packages: [{
                       "name": "MyTest",
                       "location": "/MyTest"
                   }]
               };
    
      require(["MyTest/MyTest"], function (MyTest2) {
               MyTest2.increment();
           alert(MyTest2.getValue());
                MyTest2.increment();
              alert(MyTest2.getValue());
      
    
            var x = new MyTest2();//这个是错误的,因为返回的是一个对象

    在这里遇到很多问题,第一个就是如何找到自定义的包

    dojo在寻找包的时候默认的位置是相对dojo.js的目录的

    斜杠的作用,没有斜杠,就是相对于dojo这个目录来说的
          dojoConfig = {
               parseOnLoad: true,
               packages: [{
               "name": "MyTest1",
               "location": "MyTest"}]
           };

    既然知道了是相对dojo.js文件的目录,那么就可以用相对路径,或者直接放到dojo.js文件所在的目录中:

    修改方法:用相对路径/或者直接放到dojo下面去(迁移不方便)
       var 
               dojoConfig = {
                   parseOnLoad: true,
                   packages: [{
                       "name": "MyTest1",
                       "location": "../../../MyTest"
                   }]
               };
    var  
               dojoConfig = {
               parseOnLoad: true,
               packages: [{
               "name": "MyTest1",
               "location": "/Scripts/dojo-release-1.8.3/MyTest"}]
           };

    在程序中可能往往会用下面的表示方式

    var 
               dojoConfig = {
                   parseOnLoad: true,
                   packages: [{
                       "name": "MyTest1",
                       "location": location.pathname.replace(//[^/]+$/, "") + "/MyTest"
                   }]
               };
    获取的其实是当前html文件所在的目录,
    不用/开始的就表示相对路径。
    相对路径问题:注意:相对路的文件夹符号是斜杠:/

    location获取的是当前html文件所在的位置,如果是根路径,那么location.pathname.replace(//[^/]+$/, "")返回的是一个空的字符串,可以看到这个路径跟上面第一个是一样的。下面是location对象的图解:

    下面看一个复杂的,也就是返回的是一个函数的情况,在这里我和同事讨论了半天,为什么有的可以用new,有的不可以,这就要看返回的到底是什么。

    define(["dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/text!./HTMLTemplate.htm", "dojo/dom-style",
     "dojo/_base/fx", "dojo/_base/lang"],
    function (declare, WidgetBase, TemplatedMixin, template, domStyle, baseFx, lang) {
        return declare( [WidgetBase, TemplatedMixin], {
    
            name: "liu",
            age: 25,
            templateString: template,
            baseClass: "",
            basebackgroundColor: "#fff",
            constructor: function (options) {
                declare.safeMixin(this, options);
    //            console.log("1 step");
    //            this.name = options.name;
    //            this.age = options.age;
            },
    
            postCreate: function () {
    
                var domNode = this.domNode;
    
                // Run any parent postCreate processes - can be done at any point
                this.inherited(arguments);
    
                //domStyle.set(domNode, basebackgroundColor)
    
            },
            _setNameAttr: function (av) {
                if (av != "") {
    
    
                    this._set("name", av);
                }
            },
            _setAgeAttr: function (av) {
                if (typeof av == 'number' && av.constructor == Number) {
                    if (av > 0 && av < 100) {
                        this._set("age", av);
                    }
    
    
                }
            }
    
    
    
        })
    
    
    })

    下面这个是可以正确执行的

    <div data-dojo-type="MyTest/JScriptemplate" data-dojo-props="name:'liu',age:15">press me</div>

    另外一个和同事争论的就是如果在定义的模块中没有定义构造函数,采用编程式的时候,也可以传递参数?只要在创建对象的时候采用json格式的去写,是没有问题的,这估计是dojo内部做了匹配。大家可以将上面的构造函数去掉,尝试下。

        require(["MyTest/JScriptemplate"], function (ss) {
                 var x = new ss({ "a": "3", "b": 9 });
                 alert(ss.a);
                 alert(ss.b);
             })

    模板文件很简单了:

    <div>
    <span>${name}</span>
    <span>${age}</span>
    </div>
  • 相关阅读:
    Discuz!NT代码阅读笔记(4)一切皆可配置:页面的显示
    WAP网站开发

    Discuz!NT代码阅读笔记(2)网站安装自动化论坛程序安装及初始化过程
    Discuz!NT代码阅读笔记(1)从HttpModule开始
    c#使用Transactions类完成多个数据库的事务操作(分布式事务处理)
    自我介绍 简历
    Discuz!NT 系统架构分析
    缓存应用Memcached分布式缓存简介(二)
    数组类型EDT的元素个数
  • 原文地址:https://www.cnblogs.com/zuiyirenjian/p/3393411.html
Copyright © 2011-2022 走看看