初步实现了数据自动映射到html中,动态修改对象数据也很自动更新到html。提供addProps方法-添加新增属性并初始化自动监听
代码如下:

1、abserve.js:包含数据监听实现、类似jquery的find函数--querySelector实现等(数据深度迭代版)

(function(window) {
  var methods = {
    htmlToData: function(ctner) { // html反向映射到data
      var pName = this.name,
        vName = ctner ? ctner.getAttribute('varibleName') : null;
      if (vName) {} else {
        for (let key in window) {
          if (typeof window[key] == 'object') {
            try {
              var rObj = methods.getPropByPath(window[key], pName);
              if (rObj && rObj.v != undefined) {
                vName = key;
                if (ctner) ctner.setAttribute('varibleName', key);
                break;
              }
            } catch (e) {}
          }
        }
      }
      var pPath = vName + '.' + pName + '=\'' + this.value + '\'';
      console.log(pPath);
      eval(pPath);
    },
    parseHtml: function({
      key, value, container, fn
    }) {
      var inputs = methods.querySelector("[name=" + key + "]", container);
      inputs.forEach(function(item, index, array) {
        try { /* callback 提供设值接口 */
          fn.apply(item, [value]);
        } catch (e) {
          item.value = value;
        }
        $(item).off("blur.render");
        $(item).on("blur.render", function() {
          methods.htmlToData.apply(this, [container]);
        });
      });
    },
    /*查找子节点,用法类似jquery的find函数,仅支持id,class,attr选择器,返回匹配的元素集*/
    querySelector: function find(selector, el) {
      var el = el || document;
      var m = selector.match(/([#\.\[])([\w\W]+)/i);
      var type, key, attrName, result = [];
      if (m) { /* 正则判断选择器类型 */
        if (m[1] == ".") {
          type = "class";
          key = m[2];
        } else if (m[1] == "#") {
          type = "id";
          key = m[2];
        }
        if (m[1] == "[") {
          type = "attr";
          m = m[2].match(/(\w+)=((\w+(\[\d+\])*\.*)+)/i);
          attrName = m[1];
          key = m[2];
        }
      } else {
        type = "tag";
        key = selector;
      }

      function findChild(node) {
        var c;
        for (var i = 0; i < node.childNodes.length; i++) {
          c = node.childNodes[i];
          if (type == "class" && c.className == key) result.push(c);
          else if (type == "id" && c.id == key) {
            result.push(c);
            continue;
          } else if (type == "attr" && c.getAttribute && c.getAttribute(
              attrName) == key) {
            result.push(c);
            continue;
          } else if (type == "tag" && c.tagName && c.tagName.toLowerCase() ==
            key) {
            result.push(c);
            continue;
          }
          findChild(c);
        }
      }
      findChild(el);
      return result;
    },
    getPropByPath: function(obj, path) {
      let tempObj = obj;
      path = path.replace(/\[(\w+)\]/g, '.$1');
      path = path.replace(/^\./, '');

      let keyArr = path.split('.');
      let i = 0;

      for (let len = keyArr.length; i < len - 1; ++i) {
        let key = keyArr[i];
        if (key in tempObj) tempObj = tempObj[key];
        else {
          throw new Error(
            '[render warn]: please transfer a valid prop path to form item!'
          );
        }
      }
      return {
        o: tempObj,
        k: keyArr[i],
        v: tempObj[keyArr[i]]
      };
    },
    _copyProps: function(obj, target) {
      for (var key in target) obj[key] = target[key];
    },
    _defProps: function(obj, ctx, key, value, props, path, bool) {
      /* prop参数是为了解决二次赋值操作导致key值改变,parseHtml无法获得name名 */
      (function(key, prop, props) {
        Object.defineProperty(obj, key, {
          set: function(newValue) {
            if (bool)
              methods._addProps(obj[key], newValue, ctx, path);
            else key = props[prop] = newValue;
          },
          get: function() {
            return props[prop];
          }
        });
      })(key, key, props);
      /* 实现obj.prop 和 obj.data.prop双向更新 */
      (function(ctx, key, value, props, path) {
        Object.defineProperty(props, key, {
          set: function(newValue) {
            if (key == newValue) return;
            key = newValue;
            path = path.replace(/\.*(undefined)*\.+/, '.')
              .replace(/\.(\d+)\./g, '[+$1+].').replace(
                /[+]/g,
                '');
            var propPath = path.slice(path.indexOf('.') + 1);
            if (propPath.indexOf('data.') == 0)
              propPath = propPath.replace('data.', '');
            methods.parseHtml({
              key: propPath,
              value: newValue,
              container: document.querySelector(ctx),
              fn: Vue.prototype.setValue
            });
          },
          get: function() {
            return key;
          }
        });
        props[key] = value;
      })(ctx, key, value, props, path);
    },
    _addProps: function(obj, props, ctx, path) {
      for (var key in props) {
        if (typeof props[key] == 'object') {
          methods._addProps(obj[key] = {}, props[key], ctx, path +
            '.' +
            key);
          methods._defProps(obj, ctx, key, props[key], props, path +
            '.' +
            key, true);
        } else if (typeof props[key] == 'function') obj[key] = props[
          key];
        else methods._defProps(obj, ctx, key, props[key], props, path +
          '.' + key);
      }
      return obj;
    },
    /* obj:目标对象;props:json格式属性;path:属性路径;el:渲染域容器 */
    addProps: function(obj, props, path) {
      var target = obj;
      if (path) target = methods.getPropByPath(obj, path).v;
      methods._addProps(target, props, obj.el || 'document', '.' +
        path);
    }
  };
  _ = {
    addProps: methods.addProps,
    getPropByPath: methods.getPropByPath,
    querySelector: methods.querySelector,
    parseHtml: methods.parseHtml,
    htmlToData: methods.htmlToData
  };
  Vue = function(param) {
    methods._copyProps(this, param);
    if (this.data) methods._addProps(this, this.data, this.el);
  }
  Vue.prototype = {
    addProps: function(props, path) {
      methods.addProps(this, props, path);
    }
  };
}(window));
View Code

相关文章:

  • 2022-12-23
  • 2021-08-12
  • 2021-06-26
  • 2021-12-08
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案