想問網頁 js 在 UI 渲染有什麼需注意的知識點?

學生提問

  • 想問 UI 渲染還有什麼需注意的地方和特別的渲染方法嗎?
  • 請問.innerHTML .innerText 這兩個有比 .textContent 更好用嗎?在網路上看到用 innerHTML 會有資安的疑慮。

回答

首先要先知道一些歷史演進

  • Lv1: 用原生 js 開發
  • Lv2: 用 jQuery 開發
  • Lv3: 用 前端框架開發 (Vue, Angular, React)

前端框架御三家

目前我們實戰上都是採用 Lv3 ,有了框架操作 DOM 變得非常簡單,很少很少會用到 innerHtml 這個語法


來盤點操作 DOM 原生的語法

字串轉 DOM

DOM 改 DOM

用原生語法操作程式碼比較冗長,所以多數開發者後來都使用框架做開發

// 一個最常見的範例
// 用 createElement 增加一個 DOM 節點
const str = document.createElement("em");
// 先用 JS 寫好要增加的內容
str.textContent = "1234";
// 用 appendChild() 把上面寫好的子節點掛在既有的節點下面
document.querySelector(".title").appendChild(str);

再來說說四個比較像會搞混的語法差異

  • innerText:返回可見的文字,CSS 樣式會影響(display:none 會隱藏)。
  • innerHTML:返回元素內的 HTML 標籤及其內容。
  • textContent:返回元素內的純文字,不包含 HTML 標籤。
  • outerHTML:返回整個元素及其 HTML 標籤。
<!-- 自己跑一次看看就知道 -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="example1">Hello <span style="display: none">World</span></div>
    <script>
      let div1 = document.getElementById("example1");
      console.log(div1.innerText); // Output: "Hello"
    </script>

    <div id="example2">Hello <span style="display: none">World</span></div>
    <script>
      let div2 = document.getElementById("example2");
      console.log(div2.innerHTML); // Output: "Hello <span style="display: none">World</span>"
    </script>

    <div id="example3">Hello <span style="display: none">World</span></div>
    <script>
      let div3 = document.getElementById("example3");
      console.log(div3.textContent); // Output: "Hello World"
    </script>

    <div id="example4">Hello <span style="display: none">World</span></div>
    <script>
      let div4 = document.getElementById("example4");
      console.log(div4.outerHTML); // Output: "<div id="example4">Hello <span style="display: none">World</span></div>"
    </script>
  </body>
</html>

最後說明一下實戰上怎麼處理

我們團隊開發前端專案是使用 Vue3

以下是語法範例

<script setup>
  import { ref } from "vue";

  const items = ref([{ message: "Foo" }, { message: "Bar" }]);
</script>

<template>
  <li v-for="(item, index) in items">{{ index }} - {{ item.message }}</li>
</template>

渲染出來會長這樣

<div id="app" data-v-app="">
  <li>0 - Foo</li>
  <li>1 - Bar</li>
</div>

仔細看你會發現完全沒用到原生語法就能操作 DOM

這個是框架幫忙做掉渲染 UI 的工作,開發者只要專注在操作資料即可~

先寫過原生語法再學框架對未來是最有幫助的! 直接學框架在基礎的理解上會差別人一截

DOMPurify

逼不得已用到 innerHtml 會我們會先給別人寫好的套件處理過,再使用innerHtml插入,避免一些資安問題

套件可以參考: https://github.com/cure53/DOMPurify/

動手自己試試看:

https://letswritetw.github.io/letswrite-dompurify/

1. 到上面的網址
2. 輸入 `<script>alert(1)</script>`
3. 原文說明: https://www.letswrite.tw/dompurify/

參考文章

https://www.codenong.com/718091/

https://blog.csdn.net/Alisa_94/article/details/103072299

https://ithelp.ithome.com.tw/articles/10218607

https://orandigo.github.io/blog/2020/03/22/20200322-innerText-innerHTML-textContent-outerHTML/