zoukankan      html  css  js  c++  java
  • javascript中依赖属性(Dependency Property)的实现

    好久没在首页发点东西了,昨天在js上依照wpf中依赖属性的思想尝试写了基本的功能.这里拿出来与大家分享

    Demo1 注册依赖属性

    step1 定义一个函数

    function Person() {
        this.render = function () { }
    };
    
    

    step2 注册依赖属性

    第三个参数是属性变更回调

    dp.reg(Person, "name", "terry", function (obj) {
        obj.render();
        alert(obj.oldValue);
        alert(obj.newValue);
    });
    

    setp3 修改依赖属性值

    上面的回调方法触发了,至于具体这个功能用在什么场合,你懂的

    dp.setValue(entity, "name", "zhang");
    

    Demo2 注册只读依赖属性

    下面的回调方法将会触发

    dp.regReadOnly(Person, "sex", "boy", function (obj) {
        alert(obj.newValue);
    });
    

    另外还可以添加一个属性验证回调,如下,因为年龄不可能小于0

    dp.reg(Person, "age", 25, function (obj) {
    }, function (value) {
        if (value < 1)
            return 1;
        return value;
    });
    

    Demo3 读写依赖属性

    用setValue和getValue方法

    var entity = new Person();
    
    dp.getValue(entity, "age")
    dp.setValue(entity, "name", "xinghao");
    

    Demo4 默认属性值

    在注册依赖属性时就有一个默认的值,可通过下面方法查看和恢复默认值

    dp.getDefaultValue(entity, "name");
    dp.clearValue(entity, "name");
    

    Demo5 注销依赖属性

    dp.unreg("Person", "name");
    

    说明:以上通过依赖属性注册的属性不会存在原有对象中,即注册了Person,但不会影响Person本身对象.那么久是说依赖属性是一个可插拔的功能.如果你还没有过这种属性定义的尝试的话,那么来试一下吧。我将继续完善其功能,并与大家分享(假设你还没有依赖属性的概念,也可以尝尝鲜)

    最后奉上完整代码,尚未完善,大家提意见吧

    
    (function (container) {
    
        var ORIGINAL_TYPE = "originalType",
        PREFIX = "dp"
    
        //utility
        function getPropName(obj) {
            return PREFIX + obj.originalType;
        }
    
        function getFnName(obj) {
            var fundoc = obj.prototype ? obj.toString() : obj.constructor.toString(),
            funcName = fundoc.split('(')[0].split(' ')[1];
            return funcName;
        }
    
        var dpos = [];
        container.dp = {};
    
        function propertyMetadata(propertyName, defaultValue, propertyChangedCallback) {
            this.PropertyName = propertyName;
            this.DefaultValue = defaultValue;
            this.PropertyChangedCallback = propertyChangedCallback;
        };
    
        propertyMetadata.prototype = {
            PropertyName: "",
            isReadOnly: false,
            Value: undefined,
            DefaultValue: undefined,
            CoerceValueCallback: undefined,
            PropertyChangedCallback: function () { }
        };
    
        function dpObject(entity) {
            this.objectType = entity;
            this.dmps = {};
    
        };
    
        dpObject.prototype = {
            addDmp: function (propertyName, defaultValue, propChanged, coerceValueCallback) {
                if (this.dmps[propertyName]) return;
    
                var dmp = new propertyMetadata(propertyName, defaultValue, propChanged);
                dmp.CoerceValueCallback = coerceValueCallback;
                this.dmps[propertyName] = dmp;
                return dmp;
            },
            getDmpCount: function () {
                return this.dmps.lenth;
            },
            getPropValue: function (propertyName,prop) {
                var dmp = this.dmps[propertyName];
                return dmp[prop];
            },
            getDmp: function (propertyName) {
                return this.dmps[propertyName];
            },
            clearDmp: function (propertyName) {
                this.dmps[propertyName] = undefined;
                delete this.dmps[propertyName];
            },
            setValue: function (obj, prop, newValue) {
                var dmp = this.dmps[prop];
                if (!dmp || dmp.isReadOnly) return;
    
                var oldValue = dmp.Value || dmp.DefaultValue;
    
                if (dmp.CoerceValueCallback)
                    newValue = dmp.CoerceValueCallback(newValue);
    
                if (newValue !== oldValue)
                    dmp.Value = newValue;
                if (dmp.PropertyChangedCallback) {
                    var changedArgs = { obj: obj, prop: prop, oldValue: oldValue, newValue: newValue }
                    dmp.PropertyChangedCallback(changedArgs);
                }
            },
            getValue: function (prop) {
                var dmp = this.dmps[prop];
                return dmp.Value ? dmp.Value : dmp.DefaultValue;
            },
            getDefaultValue: function (prop) {
                var dmp = this.dmps[prop];
                return dmp.DefaultValue;
            },
            clearValue: function (prop) {
                var dmp = this.dmps[prop];
                dmp.Value = undefined;
            }
        };
    
        dp.unReg = function (obj, prop) {
            var className = getFnName(obj),
            dpo = dpos[className];
            dpo.clearDmp(prop);
        };
    
        dp.isReged = function (obj, prop) {
            var className = getFnName(obj),
            dpo = dpos[className];
            if (!prop)
                return dpo.getDmpCount() > 0;
    
            return dpo.getDmp(prop) == undefined;
        };
    
        dp.isReadOnly=function(obj,prop) {
            var dpo = getDpo(obj);
            return dpo.getPropValue(prop, "isReadOnly");
        };
    
        dp.reg = function (obj, prop, value, propChanged, coerceValueCallback, isReadOnly) {
            var className = getFnName(obj),
            dpo = dpos[className] = dpos[className] || new dpObject(className);
            dpo.addDmp(prop, value, propChanged, coerceValueCallback);
            if (isReadOnly) {
                var dmp = dpo.getDmp(prop);
                dmp.isReadOnly = true;
            }
        };
        dp.regReadOnly = function (obj, prop, value, propChanged, coerceValueCallback) {
            dp.reg(obj, prop, value, null, null, true);
        };
    
        function getDpo(obj) {
            var className = getFnName(obj),
            dpo = dpos[className];
            return dpo;
        };
    
        dp.setValue = function (obj, prop, value) {
            var dpo = getDpo(obj);
            dpo.setValue(obj, prop, value);
        };
    
        dp.getValue = function (obj, prop) {
            var dpo = getDpo(obj);
            return dpo.getValue(prop, value);
        };
    
        dp.getDefaultValue = function (obj, prop) {
            var dpo = getDpo(obj);
            return dpo.getDefaultValue(prop);
        };
    
        dp.clearValue = function (obj, prop) {
            var dpo = getDpo(obj);
            dpo.clearValue(prop);
        };
    
    })(window);
    
    function Person() {
        this.render = function () { }
    };
    
    dp.reg(Person, "name", "terry", function (obj) {
        obj.render();
        alert(obj.oldValue);
        alert(obj.newValue);
    });
    
    dp.setValue(entity, "name", "zhang");
    
    dp.reg(Person, "age", 25, function (obj) {
    }, function (value) {
        if (value < 1)
            return 1;
        return value;
    });
    
    dp.regReadOnly(Person, "sex", "boy", function (obj) {
        alert(obj.newValue);
    });
    
    dp.setValue(entity, "age", -1);
    
    var entity = new Person();
    
    dp.getValue(entity, "age")
    dp.setValue(entity, "name", "xinghao");
    alert(dp.isReged(entity);
    alert(dp.getValue(entity, "name"));
    dp.getDefaultValue(entity, "name");
    dp.clearValue(entity, "name");
    alert(dp.getValue(entity, "name"));
    dp.unreg("Person", "name");
    dp.setValue(entity, "name", "zhang");
    
  • 相关阅读:
    Android手势(上,下,左和右的判断)
    我爱意甲
    程序员特有的9个坏习惯
    我爱英超
    VS2010快捷键总结(一)
    C#中导出Excel总结
    MessageDAL
    GDI+ 绘图总结
    .net中绑定日期时,只显示年月日的做法
    Vb线程控制
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2171842.html
Copyright © 2011-2022 走看看