點燈坊

失くすものさえない今が強くなるチャンスよ

使用 $refs 搭配 DOM API 產生 HTML

Sam Xiao's Avatar 2020-10-24

實務上 Vue 應該盡量使用 Model-based 寫法,專心處理 Data,HTML 則由 Vue 處理,但偶而會想直接使用 DOM API 處理 DOM,此時可使用 $refs

Version

Vue 2.6.11

Draw Text

refs000

按下 Draw Text 會動態產生 Hello World

<template>
  <div>
    <button @click="onClick">Draw Text</button>
    <div ref="canvas"/>
  </div>
</template>

<script>
let onClick = function() {
  let node = document.createTextNode('Hello World')
  this.$refs.canvas.appendChild(node)
}

export default {
  methods: {
    onClick
  }
}
</script>

第 4 行

<div ref="canvas"/>

使用 DOM API 需搭配 ID,但在 Vue 要改用 ref 取代 ID。

第 9 行

let onClick = function() {
  let node = document.createTextNode('Hello World')
  this.$refs.canvas.appendChild(node)
}
  • 使用 document.createTextNode() 建立 node
  • 使用 $refs 取得剛設定的 ref
  • 使用 appendChild() 將 node 動態加入

Draw List

refs001

按下 Draw List 會動態產生 <ul><li>

<template>
  <div>
    <button @click="onClick">Draw List</button>
    <div ref="canvas"/>
  </div>
</template>

<script>
let onClick = function() {
  let ul = document.createElement('ul')

  for (let { title } of this.books) {
    let li = document.createElement('li')
    let node = document.createTextNode(title)
    li.appendChild(node)
    ul.appendChild(li)
  }

  this.$refs.canvas.appendChild(ul)
}

export default {
  data: () => ({
    books: [
      { 'title': 'FP in JavaScript'},
      { 'title': 'RxJS in Action'},
      { 'title': 'Speaking JavaScript'}
    ]
  }),
  methods: {
    onClick
  }
}
</script>

第 9 行

let onClick = function() {
  let ul = document.createElement('ul')

  for (let { title } of this.books) {
    let li = document.createElement('li')
    let node = document.createTextNode(title)
    li.appendChild(node)
    ul.appendChild(li)
  }

  this.$refs.canvas.appendChild(ul)
}

傳統會在 HTML template 使用 v-for 建立 <ul><li>,但也可使用 DOM API 建立。

  • 使用 document.createElement() 建立 <ul><li>
  • 使用 document.createTextNode() 建立 node
  • 使用 appendChild() 動態加入 element 與 node

Conclusion

  • Vue 實務上較少使用 $refs,但若真的要直接使用 DOM API,就要改用 ref 取代 ID,使用 appendChild() 加入 node

Reference

Vue, Accessing Child Component Instances & Child Elements