假设我们有一个现有的角度组件,包括menu.component.html:
<ul>
<li><a href="/home">home</a></li>
<li><a href="/about">about</a></li>
</ul>
目标是在“关于”之后添加一个带有角度示意图的新链接
<li><a href="/contact">contact</a></li>
有任何想法吗?
假设我们有一个现有的角度组件,包括menu.component.html:
<ul>
<li><a href="/home">home</a></li>
<li><a href="/about">about</a></li>
</ul>
目标是在“关于”之后添加一个带有角度示意图的新链接
<li><a href="/contact">contact</a></li>
有任何想法吗?
您可以执行以下操作:
export function myComponent(options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
const content: Buffer | null = tree.read("./menu.component.html");
let strContent: string = '';
if(content) strContent = content.toString();
const appendIndex = strContent.indexOf('</ul>');
const content2Append = ' <li><a href="/contact">contact</a></li> \n';
const updatedContent = strContent.slice(0, appendIndex) + content2Append + strContent.slice(appendIndex);
tree.overwrite("./menu.component.html", updatedContent);
return tree;
};
}
请注意,这是一个非常原始的解决方案。nodejs 中有 DOM 解析器库,可以让你的生活更轻松(jsdom)。您可以将content2Append
变量作为输入并为您的用例清理它。
Eko的回答是正确的。我想扩展这个答案并做两件事:
使用 jsdom 和类似工具,序列化 Angular 模板要么不起作用,要么破坏任何 camelCase、[boxed]、(括号)、#tagged 属性。所以我们只会使用 jsdom 来查找我们要更新的位置。
function updateTemplate() {
return (tree: Tree) => {
const buffer = tree.read(TEMPLATE_PATH);
const content = buffer?.toString();
if (!content) {
throw new SchematicsException(`Template ${TEMPLATE_PATH} not found`);
}
// the includeLocations flag is very important here
const dom = new JSDOM(content, { includeNodeLocations: true });
const element = dom.window.document.querySelector('ul');
const locations = dom.nodeLocation(element);
if (!locations) {
throw new SchematicsException(`<ul> could not be found in ${TEMPLATE_PATH}`);
}
// now we update the template using the tree recorder
// we don't use jsdom to directly update the template
const recorder = tree.beginUpdate(TEMPLATE_PATH);
const listItem = ` <li><a href="/contact">contact</a></li>\n`
recorder.insertLeft(locations.endTag.startOffset, listItem);
tree.commitUpdate(recorder);
return tree;
};
}
同样,eko 的回答是正确的。这个答案说明了如何一起使用 jsdom 和树记录器来更新 Angular 模板——这对于将指令、事件、标签和方法插入元素、包装部分和更复杂的转换很有用。
更新:使用最新的 1.0.0rc3 Cheerio 版本,xmlMode 会自动关闭标签,这会杀死您的模板!因此,改为使用0.22.0 Cheerio版本并失去 xmlMode 选项!
我正在测试图形学,我还需要更新角度组件模板。这是一篇有用的文章:
现在,请注意,使用最新版本的cheerio,您应该使用 xmlMode 选项来加载组件模板,否则您将拥有一个完整的 HTML 文档:
https://github.com/cheeriojs/cheerio/issues/1031#issuecomment-368307598
您最终会以这种方式将一些 HTML 添加到 Angular 模板中:
function addComponent(): Rule {
return (tree: Tree) => {
const filePath = './src/app/app.component.html';
const content: Buffer | null = tree.read(filePath);
let strContent: string = '';
if(content) strContent = content.toString('utf8');
const $ = cheerio.load(strContent, {
xmlMode: true
});
const contentToInsert = `<my-comp></my-comp>`;
$.root().append(contentToInsert);
tree.overwrite(filePath, $.html());
return tree;
};
}
我希望这可以帮助:)