Hỏi - đáp Nơi cung cấp thông tin nghề nghiệp và giải đáp những thắc mắc thường gặp của bạn

Một số hàm, thuộc tính hữu ích trong VueJS mà có thể bạn không biết

I. Giới thiệu

Hôm nay mình sẽ chia sẻ một số hàm, thuộc tính hữu ích trong VueJS mà đôi khi chúng ta không để ý tới.

II. Nội dung

  1. is
  • Một số phần tử HTML, chẳng hạn như <ul>,<ol>, <table>  <select> chỉ cho phép một số thẻ nhất định là thẻ con của nó và một số phần tử như <li>,<tr>  <option> chỉ có thể xuất hiện bên trong một số phần tử khác. Điều này sẽ dẫn đến các vấn đề khi sử dụng các thành phần với các phần tử có các hạn chế như vậy. Ví dụ:
<table>
  <blog-post-row></blog-post-row>
</table>
  • Thuộc tính is sinh ra để giải quyết vấn đề này. Đoạn code trên sẽ được sửa như sau
<table>
  <tr is="blog-post-row"></tr>
</table>
  • Ngoài ra, để có được dynamic component ta sử dụng thuộc tính is kết hợp với element <component/>. Ví dụ ta có component: <my-button/>: là một button custom component và một số các icon component như:
// <download-icon />:
<template>
  <svg
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <rect width="24" height="24" fill="#E3F2FD" fill-opacity="0.01" />
    <path d="M7 10L12 15L17 10" stroke="#6200EA" stroke-width="2" />
  </svg>
</template>

Để hiển thị icon bên trong button, ta làm như sau:

  • Sử dụng prop để truyền tên của icon component muốn sử dụng
<my-button icon="download-icon"> Button </my-button>
  • Ở component button, ta xử lý như sau
<button >
    <template v-if="icon">
      <component :is="icon" /> 
    </template>
    <slot />
</button>
  • Kết quả ta sẽ được:
<button >
    <download-icon />
    <slot />
</button>
  1. v-model
  • v-model có lẽ là một trong số thuộc tính đc sử dụng nhiều nhất, tác dụng của nó là bind dự liệu 2 chiều. Nó được dùng cho các thẻ input. Ví dụ:
<input v-model="message">
<p>Message is: {{ message }}</p>
  • Khi đó value của input sẽ bằng message và khi thay đổi ô input state message của được thay đổi theo. Nó tương đương với việc thêm vào input 2 phần: 1 là v-bind, 2 là event onchange Dựa vào tính chất này, ta có thể viết lại các component input. Ví dụ:
Vue.component('custom-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})
  • Để sử dụng nó ta viết như sau
<base-checkbox v-model="lovingVue"></base-checkbox>
  1. nextTick
  • Để nâng cao hiệu năng, Vue sẽ không cập nhật DOM lại ngay bất cứ một stage nào thay đổi. Vue sẽ cập nhật DOM theo một cách bất đồng bộ. Nó có một cách để giữ các bản cập nhật này được "lưu trữ" cho đến khi nó được áp dụng. Nó tạo ra một queue của các cập nhật và đẩy chúng ra khi cần thiết. Sau đó, DOM được "vá" và được cập nhật lên phiên bản mới nhất. Đoạn code sau sẽ cho bạn thấy rõ điều này.
const example = Vue.component('example', {
  template: '<p>{{ message }}</p>',
  data: function () {
    return {
      message: 'not updated'
    }
  },
  mounted () {
    this.message = 'updated'

		console.log(
    	'outside nextTick callback:', this.$el.textContent
    ) // => 'not updated'

    this.$nextTick(() => {
      console.log(
        'inside nextTick callback:', this.$el.textContent
      ) // => 'updated'
    })
  }
})


new Vue({
  el: '#app',
	render: h => h(example)
})

Kết quả là:

"outside nextTick callback:" "not updated"
"inside nextTick callback:" "updated"

Điều này dẫn đến tình trạng ở một số trường hợp, đoạn code của chúng ta sẽ không khoạt động theo ý mình muốn

const example = Vue.component('example', {
 template:`
 <div>
     <input id="demo" v-if="isShow" type="text">
     <button @click="onClick">Click Me!</button>
 </div>
  `,
 data: function () {
   return {
     isShow: false
   }
 },
 methods: {
   onClick(event) {
     this.isShow = !this.isShow;
     if(this.isShow) {
         document.getelementbyid("demo').focus() //focus vào ô input
     }
   }
 }
})


new Vue({
 el: '#app',
   render: h => h(example)
})
  • Đoạn code trên thực hiện chức năng là: khi bấm vào nút 'Click me' nếu đã có ô input id = "demo" rồi thì ẩn ô input đi, nếu không hiển thị ô input có id là "demo" và focus vào ô input đó. Tuy nhiên khi chạy thì ta thấy báo lỗi là
Error in v-on handler: 'TypeError: Cannot read properties of null (reading 'focus')'

Để đoạn code trên có thể chạy được ta sửa như sau

Cách 1: dùng setTimeout 

onClick(event) {
  this.isShow = !this.isShow;
  if(this.isShow) {
      setTimeout(() => {
           document.getElementById('demo').focus();
      }, 0);
  }
}

Cách 2: dùng nextTick

onClick(event) {
     this.isShow = !this.isShow;
     if(this.isShow) {
        this.$nextTick(() => {
            document.getElementById('demo').focus();
        })
    }
}

Ở cách thứ nhất, khi sử dụng setTimeout, ta có thể gặp nhiều rủi ro nếu không biết quản lý setTimeout một cách hợp lý. Vì vậy mình khuyên mọi người nên dùng cách 2

III. Kết

Mình vừa trình bày 3 tip trong Vue mà mình cảm thấy thú vị. Nếu có đóng góp xin vui lòng để lại dưới comment. Cảm ơn các bạn vì đã đọc. Hẹn gặp các bạn trong các bài viết tiếp theo.

Nguồn: Vibo