一、功能:邮件展示和复制
展示邮件内容,邮件的每一行数据都来自后端接口
前端根据产品类型,判断当前行是否显示
下方有一个复制按钮,复制后要保持原有的格式
二、现状代码
现状代码简化如下:
<template>
<div class="wrap">
<div class="email-content">
<p>Dear team,</p>
<p>{{ data.greet }}</p>
<br />
<p>label1: {{ data.value1 }}</p>
<p v-if="[1, 3].includes(type)">label2: {{ data.value2 }}</p>
<p>label3: {{ data.value3 }}</p>
<p v-if="[2].includes(type)">label4: {{ data.value4 }}</p>
</div>
<button class="btn" @click="handleCopy">复制</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { copyText } from '@/utils'
const type = ref(2)
const data = ref({
greet: 'greet',
value1: 'value1',
value2: 'value2',
value3: 'value3',
value4: 'value4'
})
const handleCopy = () => {
let content = ''
if (type.value === 1) {
// 为了保持换行格式,使用了模板字符串
content = `Dear team,
${data.value.greet}
label1: ${data.value.value1}
label2: ${data.value.value2}
label3: ${data.value.value3}`
} else if (type.value === 2) {
content = `Dear team,
${data.value.greet}
label1: ${data.value.value1}
label3: ${data.value.value3}
label4: ${data.value.value4}`
} else {
// ...
}
copyText(content)
}
</script>
三、代码分析
每次都要依据产品类型,重新构建复制的内容
产品类型越多,if条件越多,不便于维护
并且每次修改和增加产品,不仅要修改HTML,还要修改JS
四、代码优化
问题:能不能将展示在页面上的HTML,直接转换成我们复制需要的内容呢?
解决办法:首先,最外层div增加ID选择器: <div id="email-conten" class="email-content">
然后,修改新的复制方法如下:
const handleCopy = () => {
let content = ''
// 邮件的div元素
const dom = document.getElementById('email-content')
if (dom) {
// DOM相关API访问或修改性能消耗大,用局部变量缓存起来
const children = dom.children
const len = children.length
// 依据children属性遍历它的的元素节点
for (let i = 0; i < len; i++) {
// 取出节点内的内容,并增加换行符
content += `${children[i].innerHTML}\n`
}
copyText(content)
}
}
优点:不仅代码简短,而且每次修改和增加产品类型时,只要调整HTML,不再需要调整JS,便于维护
五、知识点整理
(1)children和childNodes的区别?
children 获取子代的所有元素节点(不包括文本节点和注释节点)
childNodes获取子代所有节点(包括文本节点和注释节点)
(2)innerHTML和outerHTML的区别?
将元素中的 HTML 获取为字符串形式,innerHTML不包括元素自身,outerHTML包括元素本身
(3)关于js复制
export const copyText = (text) => {
if (navigator.clipboard) {
navigator.clipboard.writeText(text)
} else {
const textarea = document.createElement('textarea')
document.body.appendChild(textarea)
textarea.style.position = 'fixed'
textarea.style.top = '0'
textarea.style.left = '0'
textarea.style.opacity = '0'
textarea.value = text
textarea.select()
document.execCommand('copy', true)
document.body.removeChild(textarea)
}
}