使用 vanilla javascript 在 React 页面中添加元标记
Add a meta tag in React page with vanila javascript
我想在没有外部库的情况下使用普通 javascript 在 React 组件上添加元标记。我已将其添加到 useEffect
挂钩中,如下所示:
useEffect(() => {
const ogTitle = document.createElement('meta');
const ogImage = document.createElement('meta');
const ogDescription = document.createElement('meta');
if(classPage?.name) {
ogTitle.setAttribute('property', 'og:title');
ogTitle.content= classPage?.name;
document.getElementsByTagName('head')[0].appendChild(ogTitle);
}
if(classPage?.pictureUrl) {
ogImage.setAttribute('property', 'og:image');
ogImage.content= classPage?.pictureUrl;
document.getElementsByTagName('head')[0].appendChild(ogImage);
}
if(classPage?.description) {
ogDescription.setAttribute('property', 'og:description');
ogDescription.content= classPage?.description;
document.getElementsByTagName('head')[0].appendChild(ogDescription);
}
const ogUrl = document.createElement('meta');
ogUrl.setAttribute('property', 'og:url');
ogUrl.content = document.location.href;
document.getElementsByTagName('head')[0].appendChild(ogUrl);
}, [classPage]);
当我打开 chrome 检查器时我可以看到结果,它们在 head
标签中。但是当我转到其他页面时,我看到元标记附加在下面,而不是替换上一页中的值。像这样:
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
<meta property="og:title" content="Testing 2">
<meta property="og:image" content="https://images.unsplash.com/photo-1616008783091-189d8c5efd61?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxODkyMzl8MHwxfHJhbmRvbXx8fHx8fHx8fDE2MjEzMzUzMzY&ixlib=rb-1.2.1&q=80&w=1080">
<meta property="og:description" content="testing">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/myfirstclasscc319a1ab57e4874be991a346e6fa86e">
<meta property="og:title" content="My First Class">
<meta property="og:image" content="https://images.unsplash.com/photo-1623001398544-5c7f047842ca?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxODkyMzl8MHwxfHJhbmRvbXx8fHx8fHx8fDE2MjM4NjAwMjA&ixlib=rb-1.2.1&q=80&w=1080">
<meta property="og:description" content="jhlghjul iuiuiu iouiuii">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/myfirstclasscc319a1ab57e4874be991a346e6fa86e">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
<meta property="og:title" content="Testing 2">
<meta property="og:image" content="https://images.unsplash.com/photo-1616008783091-189d8c5efd61?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxODkyMzl8MHwxfHJhbmRvbXx8fHx8fHx8fDE2MjEzMzUzMzY&ixlib=rb-1.2.1&q=80&w=1080">
<meta property="og:description" content="testing">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
我试过这样的清理功能:
return () => {
ogTitle.removeAttribute('property')
ogTitle.content = '';
document.getElementsByTagName('head')[0].removeChild(ogTitle)
......
}
但是出现这个错误:
NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
所以我的问题是如何使用普通 javascript、无库
在 React 组件中添加元标记
您的清理函数是:
- 正在创建一个新的元元素
- 从中删除 属性 属性(即使它没有)
- 设置内容属性为空字符串
- 尝试将其从头部移除(即使您一开始从未将其添加到头部)
如果要删除之前添加到 DOM 的元素,则需要获取对该元素的引用。
正在创建一个新元素…创建一个新元素。它没有找到现有的。
您已经引用了 ogTitle
中的元元素和您创建的其他变量。使用那些。
您应该直接在清理回调中删除附加的元元素。
useEffect(() => {
const ogTitle = document.createElement('meta');
const ogImage = document.createElement('meta');
const ogDescription = document.createElement('meta');
if(classPage?.name) {
ogTitle.setAttribute('property', 'og:title');
ogTitle.content= classPage?.name;
document.getElementsByTagName('head')[0].appendChild(ogTitle);
}
if(classPage?.pictureUrl) {
ogImage.setAttribute('property', 'og:image');
ogImage.content= classPage?.pictureUrl;
document.getElementsByTagName('head')[0].appendChild(ogImage);
}
if(classPage?.description) {
ogDescription.setAttribute('property', 'og:description');
ogDescription.content= classPage?.description;
document.getElementsByTagName('head')[0].appendChild(ogDescription);
}
const ogUrl = document.createElement('meta');
ogUrl.setAttribute('property', 'og:url');
ogUrl.content = document.location.href;
document.getElementsByTagName('head')[0].appendChild(ogUrl);
return () => {
for (const metaElement of [ogTitle, ogImage, ogDescription, ogUrl]) {
metaElement.parentNode.removeChild(metaElement)
}
}
}, [classPage]);
如前所述,问题似乎是您每次都在创建元素。在我看来,制作一个 meta adder 函数是一个好主意,如下所示:
const metaAdder = (queryProperty, value) => {
// Get an element if it exists already
let element = document.querySelector(`meta[${queryProperty}]`);
// Check if the element exists
if (element) {
// If it does just change the content of the element
element.setAttribute("content", value);
} else {
// It doesn't exist so lets make a HTML element string with the info we want
element = `<meta ${queryProperty} content="${value}" />`;
// And insert it into the head
document.head.insertAdjacentHTML("beforeend", element);
}
};
然后您可以调用此函数并传递您希望更改的元标记的 property/name 以及值。如果元标记存在,它将更改内容,否则将创建并插入它。
在你的例子中:
if(classPage?.name) {
metaAdder('property="og:title"', classPage.name)
}
我已经删除了你对 className 是否存在的第二次检查,因为我们已经在包装 if 语句中检查过了。
如果您希望更改 属性 内容以外的内容,您可以更改函数以获取对象。
我想在没有外部库的情况下使用普通 javascript 在 React 组件上添加元标记。我已将其添加到 useEffect
挂钩中,如下所示:
useEffect(() => {
const ogTitle = document.createElement('meta');
const ogImage = document.createElement('meta');
const ogDescription = document.createElement('meta');
if(classPage?.name) {
ogTitle.setAttribute('property', 'og:title');
ogTitle.content= classPage?.name;
document.getElementsByTagName('head')[0].appendChild(ogTitle);
}
if(classPage?.pictureUrl) {
ogImage.setAttribute('property', 'og:image');
ogImage.content= classPage?.pictureUrl;
document.getElementsByTagName('head')[0].appendChild(ogImage);
}
if(classPage?.description) {
ogDescription.setAttribute('property', 'og:description');
ogDescription.content= classPage?.description;
document.getElementsByTagName('head')[0].appendChild(ogDescription);
}
const ogUrl = document.createElement('meta');
ogUrl.setAttribute('property', 'og:url');
ogUrl.content = document.location.href;
document.getElementsByTagName('head')[0].appendChild(ogUrl);
}, [classPage]);
当我打开 chrome 检查器时我可以看到结果,它们在 head
标签中。但是当我转到其他页面时,我看到元标记附加在下面,而不是替换上一页中的值。像这样:
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
<meta property="og:title" content="Testing 2">
<meta property="og:image" content="https://images.unsplash.com/photo-1616008783091-189d8c5efd61?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxODkyMzl8MHwxfHJhbmRvbXx8fHx8fHx8fDE2MjEzMzUzMzY&ixlib=rb-1.2.1&q=80&w=1080">
<meta property="og:description" content="testing">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/myfirstclasscc319a1ab57e4874be991a346e6fa86e">
<meta property="og:title" content="My First Class">
<meta property="og:image" content="https://images.unsplash.com/photo-1623001398544-5c7f047842ca?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxODkyMzl8MHwxfHJhbmRvbXx8fHx8fHx8fDE2MjM4NjAwMjA&ixlib=rb-1.2.1&q=80&w=1080">
<meta property="og:description" content="jhlghjul iuiuiu iouiuii">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/myfirstclasscc319a1ab57e4874be991a346e6fa86e">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
<meta property="og:title" content="Testing 2">
<meta property="og:image" content="https://images.unsplash.com/photo-1616008783091-189d8c5efd61?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxODkyMzl8MHwxfHJhbmRvbXx8fHx8fHx8fDE2MjEzMzUzMzY&ixlib=rb-1.2.1&q=80&w=1080">
<meta property="og:description" content="testing">
<meta property="og:url" content="http://localhost:3000/ClassReadOnly/testing21186f6938be44682b8ccdc95827344b5">
我试过这样的清理功能:
return () => {
ogTitle.removeAttribute('property')
ogTitle.content = '';
document.getElementsByTagName('head')[0].removeChild(ogTitle)
......
}
但是出现这个错误:
NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
所以我的问题是如何使用普通 javascript、无库
在 React 组件中添加元标记您的清理函数是:
- 正在创建一个新的元元素
- 从中删除 属性 属性(即使它没有)
- 设置内容属性为空字符串
- 尝试将其从头部移除(即使您一开始从未将其添加到头部)
如果要删除之前添加到 DOM 的元素,则需要获取对该元素的引用。
正在创建一个新元素…创建一个新元素。它没有找到现有的。
您已经引用了 ogTitle
中的元元素和您创建的其他变量。使用那些。
您应该直接在清理回调中删除附加的元元素。
useEffect(() => {
const ogTitle = document.createElement('meta');
const ogImage = document.createElement('meta');
const ogDescription = document.createElement('meta');
if(classPage?.name) {
ogTitle.setAttribute('property', 'og:title');
ogTitle.content= classPage?.name;
document.getElementsByTagName('head')[0].appendChild(ogTitle);
}
if(classPage?.pictureUrl) {
ogImage.setAttribute('property', 'og:image');
ogImage.content= classPage?.pictureUrl;
document.getElementsByTagName('head')[0].appendChild(ogImage);
}
if(classPage?.description) {
ogDescription.setAttribute('property', 'og:description');
ogDescription.content= classPage?.description;
document.getElementsByTagName('head')[0].appendChild(ogDescription);
}
const ogUrl = document.createElement('meta');
ogUrl.setAttribute('property', 'og:url');
ogUrl.content = document.location.href;
document.getElementsByTagName('head')[0].appendChild(ogUrl);
return () => {
for (const metaElement of [ogTitle, ogImage, ogDescription, ogUrl]) {
metaElement.parentNode.removeChild(metaElement)
}
}
}, [classPage]);
如前所述,问题似乎是您每次都在创建元素。在我看来,制作一个 meta adder 函数是一个好主意,如下所示:
const metaAdder = (queryProperty, value) => {
// Get an element if it exists already
let element = document.querySelector(`meta[${queryProperty}]`);
// Check if the element exists
if (element) {
// If it does just change the content of the element
element.setAttribute("content", value);
} else {
// It doesn't exist so lets make a HTML element string with the info we want
element = `<meta ${queryProperty} content="${value}" />`;
// And insert it into the head
document.head.insertAdjacentHTML("beforeend", element);
}
};
然后您可以调用此函数并传递您希望更改的元标记的 property/name 以及值。如果元标记存在,它将更改内容,否则将创建并插入它。
在你的例子中:
if(classPage?.name) {
metaAdder('property="og:title"', classPage.name)
}
我已经删除了你对 className 是否存在的第二次检查,因为我们已经在包装 if 语句中检查过了。
如果您希望更改 属性 内容以外的内容,您可以更改函数以获取对象。