Skip to content

Dashboard

Sử dụng Optional Chaning trong template của Vue?

Created by Admin

Trường hợp lỗi hiển thị

Ví dụ khi chúng ta muốn hiển thị giá trị trong object ra template

<template>
  <p>{{ data.user.name }}</p>
</template>

Trong trường hợp này nếu thuộc tính user không tồn tại, trình duyệt sẽ báo lỗi

Error in render: "TypeError: Cannot read property 'name' of undefined"

Và nó có thể khiến cho một một số component của thư viện UI không hiển thị, vậy nên có một cách đó là check if trước khi hiển thị

<template>
  <p>{{ data.user && data.user.name }}</p>
</template>

Nhưng mỗi lần phải check như vậy đối với các thuộc tính được lồng trong nhiều object thì nó sẽ trở thành như này

<template>
  <p>
    {{ 
      data.obj1
      && data.obj1.obj2
      && data.obj1.obj2.obj3
      && data.obj1.obj2.obj3.obj4
      ...
    }}
  </p>
</template>

Rất dài dòng và mệt mỏi

Optional chaining là gì

Được giới thiệu trong ES2020 của javascript, optional chaining ?. giúp cho việc truy cập đến các phần tử trong object ngay cả khi object không tồn tại

Có 3 kiểu cú pháp trong đấy 2 kiểu gọi đến phần tử và 1 kiểu gọi đến phương thức trong object

data?.obj
data?.[obj]
data.method?.()

Hiện tại optional chaining mới chỉ được hỗ trợ trên template của Vue 3, còn Vue 2 khi sử dụng sẽ báo lỗi

SyntaxError: Unexpected token 

Nên mình sẽ hướng dẫn cách cài đặt để có thể sử dụng optional chaining trên template của Vue 2

Cài đặt biên dịch Optional Chaining

Sử dụng thư viện vue-template-babel-compiler để biên dịch

Cài đặt

yarn add -D vue-template-babel-compiler

Cấu hình tại vue.config.js

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => {
        options.compiler = require('vue-template-babel-compiler')
        return options
      })
  }
}

Hoặc nếu sử dụng webpack để biên dịch vue

// webpack.config.js
module: {
  rules: [
    {
      test: /\.vue$/,
      loader: "vue-loader",
      options: {
        compiler: require("vue-template-babel-compiler"),
      },
    },
  ],
},

Với trường hợp sử dụng Unit test với Jest cũng cần phải cấu hình để có thể biên dịch được trên môi trường test

// jest.config.js
module.exports = {
  transform: {
    '.*\\.(vue)$': 'vue-jest',
  },
  globals: {
    'vue-jest': {
      templateCompiler: {
        compiler: require('vue-template-babel-compiler'),
        transformAssetUrls: true,
      },
    },
  },
};

Lưu ý: phiên bản của vue-jest phải lớn hơn hoặc bằng 4.0.0 và jest nhỏ hơn hoặc bằng 26.6.3.

Sử dụng Optional Chaining với template

Và bây giờ chúng ta chỉ cần viết thế này là trình duyệt không báo lỗi khi khi user không tồn tại nữa

<template>
  <p>{{ data?.user?.name }}</p>
</template>

Nhưng trên màn hình lại hiển thị ra undefined

Có một cách mọi người thường dùng là kết hợp với nullish coalescing operator để hiển thị ra giá trị rỗng thay vì undefined

<template>
  <p>{{ data?.user?.name ?? '' }}</p>
</template>

Cách hay hơn là sử dụng v-text, nó sẽ kiểm tra giá thị rồi mới render ra dom còn không thì sẽ không render, một directive rất hay nhưng lại bị rất nhiều người bỏ qua

<template>
  <p v-text="data?.user?.name" />
</template>

Sự kết hợp hoàn hảo

Source: https://viblo.asia/p/su-dung-optional-chaning-trong-template-cua-vue-Do754OMBlM6