HTML5 使用 Javascript 解析的嵌套数据-* 属性不是 return 嵌套对象

HTML5 nested data-* attributes parsed with Javascript don't return a nested object

我陷入了 html5 数据属性的概念。该属性允许嵌套,如:

<div data-user--name="John" data-user--surname="Doe"></div>

我以前见过插件(比如 select2),其中一些插件使用以下类似的语法来进行 AJAX 调用:

<div data-ajax--url="my/url" data-ajax--method="POST">

这段后台代码转换为 javascript 中的数据集,return 是这样的:

data = { 
    ajax: { 
        url: "my/url", 
        method: "POST"
    }
}

但在实践中,vanilla javascript 的 dataset 和 jQuery data() 方法 return 不同的对象内容。

Javascript

var el = document.getElementsByTagName("div")[0];
el.innerHTML = "<pre>"+JSON.stringify(el.dataset)+"</pre>";
<div data-ajax--url="my/url" data-ajax--method="POST"></div>

jQuery 1.x

$('div').html("<pre>"+JSON.stringify($('div').data())+"</pre>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div data-ajax--url="my/url" data-ajax--method="POST"></div>

jQuery 2.x

$('div').html("<pre>"+JSON.stringify($('div').data())+"</pre>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-ajax--url="my/url" data-ajax--method="POST"></div>


错误的代码似乎是 jQuery 1.x 版本,因为在 2.x 版本中 jQuery returns 与 vanilla Javascript。我发现了一个相关的错误,因此得到确认:https://github.com/select2/select2/issues/2969

但是我找不到使用嵌套 html 语法构造嵌套 javascript 对象的位置,如下例所示:

{ 
    ajax: { 
       url: "my/url"
       method: "POST"
    }
}

是否有任何 Javascript 方法或 polyfill 使此类对象读取 data-* HTML 属性?是否可以解析数据 javascript 字符串(即 ajax-Method)和 return 嵌套对象(ajax.method)?

function parseDataset(dataset) {
    data = {};
    for(var i = 0; i < Object.keys(dataset).length; i++) {
        var key = Object.keys(dataset)[i];
        var value = dataset[key];
        var splat = key.split("-");
        console.log(key, data, splat);
        if(!data[splat[0]]) {
            data[splat[0]] = {};
        }
        data[splat[0]][splat[1]] = value;
    }
    return data;
}

未经测试,但应该可以。将 el.dataset 传递到方法中,得到一个 data 对象,如:

data = {
    'ajax': {
        'Method': 'POST',
        'Url': 'my/url'
    }
};

运行 完全相同的需求,但@artofcode 的回答只解析了 2 个级别。所以我必须弄清楚如何解析无限数量的级别。这是我的解决方案,没有限制级别,基于原始答案。

function parseNestedDataSet(data_set) {
    var keys = Object.keys(data_set);
    var data = {};
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        var value = data_set[key];
        var splat = key.split('-');

        data = parseNestedDataSetKey(splat, value, data);
    }

    return data;
}

function parseNestedDataSetKey(keys, value, data) {
    data = data || {};
    var key = keys[0].toLowerCase();

    // Not tested, but should convert to camel case
    // var key = keys[0].replace(/-([a-z])/g, function (g) {
    //      return g[1].toUpperCase();
    // });

    if (!data[key]) {
        data[key] = {};
    }

    if (keys.length > 1) {
        keys.splice(0, 1);
        data[key] = parseNestedDataSetKey(keys, value, data[key]);
    } else {
        data[key] = value;
    }

    return data;
}

没有彻底测试,但它适用于我的情况,例如:

  • data-buttons--btn1--title;
  • data-buttons--btn1--icon;
  • data-buttons--btn2--title.