【代码优化】记一次邮件复制功能的代码优化

325 阅读2分钟

一、功能:邮件展示和复制

image.png

展示邮件内容,邮件的每一行数据都来自后端接口

前端根据产品类型,判断当前行是否显示

下方有一个复制按钮,复制后要保持原有的格式

二、现状代码

现状代码简化如下:

<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)
  }
}