javascript/jquery 对 Angular 的 'ng-repeat' 函数的纯 javascript/ jquery 解决方案与数据属性?
Pure javascript/ jquery solution to Angular's 'ng-repeat' function with data-attributes?
我正在尝试创建一个类似于 Angular JS 的 ng-repeat
的自定义转发器函数来迭代数据。我想纯粹用 javascript/ jquery 来做这件事并利用 html data-attributes
.
例如,假设我有这个 html
<tr data-repeat="datas">
<td data-repeat-value="data.name">--</td>
<td data-repeat-value="data.email">--</td>
</tr>
我想创建一个足够智能的函数来查看这个 html 并映射它需要的许多 <tr>
和 <td>
并吐出数据正确。
如果没有数据属性,js 解决方案将如下所示
${datas.map(data =>
`<tr>
<td>${data.name}</td>
<td>${data.email}</td>
</tr>`).join("")
}`;
但是我该如何编写 js 来利用 data-attributes
?
我有一个 codepen 显示没有 data-attributes
的工作版本和一个有 data-attributes
.
的非工作版本
任何帮助或指导将不胜感激!
解决方法如下:
getApiData(url, function(apidata){
const $template = $('[data-repeat-new]');
const $container = $template.parent();
$template.remove();
$container.append(
apidata.map(data =>{
const $snippet = $template.clone(true);
$snippet.find('[data-repeat-value-new]').each((i, el) => {
$(el).text(eval($(el).data('repeat-value-new')));
});
return $snippet;
})
);
});
完整示例在这里:https://codepen.io/anon/pen/JQWVGG?editors=0010(唯一的变化是在 // Not Working
块中)。
它的作用:
- 找到一个 DOM 片段,它将成为我们的模板(匹配
[data-repeat-new]
选择器的片段)
- 存储对该片段父元素的引用——我们要插入新内容的容器
- 删除该片段,因为我们不想在最终输出中看到模板
- 对于每个数据元素,它执行以下操作:
- 克隆模板
- 搜索所有需要插入值的节点(即匹配
[data-repeat-value-new]
选择器的节点)
- 并且对于每个这样的节点,它用评估的表达式替换节点的内容(表达式来自
data-repeat-value-new
属性的值,并且我们在 eval
的上下文中有 data
变量,所以, 一切正常)
- 之后,所有这些克隆的模板都附加到容器
那个 eval
调用可能看起来很危险,所以:
- 你可以制作简单的表达式解析器,将可能的表达式减少到 JS 的某个子集,例如它可能只能从固定数组中获取元素(即像
data.property
或 data.property[0]
这样的表达式)
- 或者你可以保持原样,因为这个评估发生在客户端,代码源是 DOM 节点——如果攻击者可以在你的 DOM 中设置任意值,他可能可以也执行任何其他代码
和 data-repeat-new
的注释重新值:您在代码中获取 API 数据,但您从未分配它,所以,我不确定如何解释它的值属性。一种方法是提供一些数据存储库,其中有带有名称的数组,如下所示:
const repo = {
data1: [{id: 'rec1'}, {id: 'rec2'}, {id: 'rec3'}]
};
然后在您的代码中您可以这样做:
const $template = $('[data-repeat-new]');
const $container = $template.parent();
$template.remove();
const data = repo[$template.data('repeat-new')];
$container.append(
data.map(data =>{
const $snippet = $template.clone(true);
$snippet.find('[data-repeat-value-new]').each((i, el) => {
$(el).text(eval($(el).data('repeat-value-new')));
});
return $snippet;
})
);
我正在尝试创建一个类似于 Angular JS 的 ng-repeat
的自定义转发器函数来迭代数据。我想纯粹用 javascript/ jquery 来做这件事并利用 html data-attributes
.
例如,假设我有这个 html
<tr data-repeat="datas">
<td data-repeat-value="data.name">--</td>
<td data-repeat-value="data.email">--</td>
</tr>
我想创建一个足够智能的函数来查看这个 html 并映射它需要的许多 <tr>
和 <td>
并吐出数据正确。
如果没有数据属性,js 解决方案将如下所示
${datas.map(data =>
`<tr>
<td>${data.name}</td>
<td>${data.email}</td>
</tr>`).join("")
}`;
但是我该如何编写 js 来利用 data-attributes
?
我有一个 codepen 显示没有 data-attributes
的工作版本和一个有 data-attributes
.
任何帮助或指导将不胜感激!
解决方法如下:
getApiData(url, function(apidata){
const $template = $('[data-repeat-new]');
const $container = $template.parent();
$template.remove();
$container.append(
apidata.map(data =>{
const $snippet = $template.clone(true);
$snippet.find('[data-repeat-value-new]').each((i, el) => {
$(el).text(eval($(el).data('repeat-value-new')));
});
return $snippet;
})
);
});
完整示例在这里:https://codepen.io/anon/pen/JQWVGG?editors=0010(唯一的变化是在 // Not Working
块中)。
它的作用:
- 找到一个 DOM 片段,它将成为我们的模板(匹配
[data-repeat-new]
选择器的片段) - 存储对该片段父元素的引用——我们要插入新内容的容器
- 删除该片段,因为我们不想在最终输出中看到模板
- 对于每个数据元素,它执行以下操作:
- 克隆模板
- 搜索所有需要插入值的节点(即匹配
[data-repeat-value-new]
选择器的节点) - 并且对于每个这样的节点,它用评估的表达式替换节点的内容(表达式来自
data-repeat-value-new
属性的值,并且我们在eval
的上下文中有data
变量,所以, 一切正常)
- 之后,所有这些克隆的模板都附加到容器
那个 eval
调用可能看起来很危险,所以:
- 你可以制作简单的表达式解析器,将可能的表达式减少到 JS 的某个子集,例如它可能只能从固定数组中获取元素(即像
data.property
或data.property[0]
这样的表达式) - 或者你可以保持原样,因为这个评估发生在客户端,代码源是 DOM 节点——如果攻击者可以在你的 DOM 中设置任意值,他可能可以也执行任何其他代码
和 data-repeat-new
的注释重新值:您在代码中获取 API 数据,但您从未分配它,所以,我不确定如何解释它的值属性。一种方法是提供一些数据存储库,其中有带有名称的数组,如下所示:
const repo = {
data1: [{id: 'rec1'}, {id: 'rec2'}, {id: 'rec3'}]
};
然后在您的代码中您可以这样做:
const $template = $('[data-repeat-new]');
const $container = $template.parent();
$template.remove();
const data = repo[$template.data('repeat-new')];
$container.append(
data.map(data =>{
const $snippet = $template.clone(true);
$snippet.find('[data-repeat-value-new]').each((i, el) => {
$(el).text(eval($(el).data('repeat-value-new')));
});
return $snippet;
})
);