Fitur Vue untuk Diingat

Kami di tim Ptah memutuskan untuk melangkah lebih jauh dari SPA biasa dan mencoba menggunakan Vue sebagai perancang laman landas. Dan sekarang kami ingin berbagi bagian dari pengalaman kami.

Artikel ini terutama untuk mereka yang baru saja mulai bekerja dengan Vue dan ingin tahu lebih banyak fitur dan kemampuannya. Di sini saya ingin berbicara tentang beberapa fitur kerangka kerja, yang sering tetap terlupakan oleh pengembang pemula.

Merender fungsi


Templat komponen adalah salah satu hal yang disukai pengembang untuk Vue. Mereka sederhana dan logis, terima kasih kepada mereka kerangka kerja memiliki ambang masuk yang rendah. Sintaks template sudah cukup dalam 90% kasus untuk menulis kode yang logis dan indah. Tetapi apa yang harus dilakukan jika Anda berada di sisa 10%, dan Anda tidak dapat menulis komponen yang ringkas? Fungsi render akan membantu Anda.

Mari kita lihat apa yang digunakannya contoh dari dokumentasi:

Vue.component('anchored-heading', {
 render: function (createElement) {
   return createElement(
     'h' + this.level,   //  
     this.$slots.default //   
   )
 },
 props: {
   level: {
     type: Number,
     required: true
   }
 }
})

Komponen heading berlabuh menerima properti level dan menggambar tag judul. Demikian rekaman

<anchored-heading :level="1">, !</anchored-heading>

Akan dikonversi menjadi

<h1>, !</h1>

Jika komponen ini dideskripsikan menggunakan templat standar, itu akan berisi hingga 6 v-jika kondisi yang menggambarkan berbagai tingkat tajuk:

<h1 v-if="level === 1">
 <slot></slot>
</h1>
<h2 v-if="level === 2">
 <slot></slot>
</h2>
<h3 v-if="level === 3">
 <slot></slot>
</h3>
<h4 v-if="level === 4">
 <slot></slot>
</h4>
<h5 v-if="level === 5">
 <slot></slot>
</h5>
<h6 v-if="level === 6">
 <slot></slot>
</h6>

Bagaimana itu bekerja?


Metode render mengambil dua argumen. Argumen pertama untuk createElement adalah fungsi yang menjelaskan elemen Vue mana yang harus dibuat. Di komunitas, sudah biasa menyingkat createElement menjadi satu huruf - h . Argumen kedua adalah konteks , untuk mengakses data konteks.

createElement membutuhkan tiga argumen:

  1. Item yang akan dibuat. Ini bukan hanya tag HTML, tetapi juga nama komponen. Argumen ini diperlukan;
  2. Objek dengan data. Ini mungkin berisi daftar kelas, gaya, parameter input untuk komponen, metode untuk menangani acara, dll. Untuk detail lebih lanjut, lihat dokumentasi. Argumen opsional;
  3. Simpul virtual anak. Ini bisa berupa string atau array. Pada contoh di atas, ini adalah ini. $ Slots.default .

Fungsi render dapat membantu dalam situasi yang paling tidak terduga. Misalnya, dalam Ptah, kita sering perlu menggunakan tag gaya di dalam halaman agar beberapa elemen desainer berfungsi dengan baik. Namun, Vue melarang penggunaan tag ini di dalam komponen template . Batasan ini mudah dilewati berkat pembungkus kecil:

Vue.component('v-style', {
 render: function (h) {
   return h('style', this.$slots.default)
 }
})

Sekarang di dalam templat, alih-alih tag gaya , Anda dapat menggunakan v-style .

Jadi, segera setelah Anda mulai merasa bahwa fitur-fitur standar templat Vue tidak cukup - pikirkan tentang fungsi-fungsi Render. Mereka terlihat rumit hanya pada pandangan pertama, tetapi Anda dapat menggunakan semua fitur yang disediakan JS di dalamnya.

Mixin


Apakah Anda memiliki beberapa komponen serupa dengan kode duplikat? Mixin atau kotoran akan membantu mematuhi prinsip KERING - fungsi mixin dapat digunakan di beberapa komponen sekaligus.

Mari kita ambil contoh. Katakanlah kita memiliki 2 komponen dengan logika yang sama:

export default  {
  name: 'TextElement',

  data () {
    return {
      elementName: 'Text',
      showEditor: false,
      editor: null
    }
  },
  
  methods: {
    initEditor () {
      this.showEditor = true
      this.editor = new Editor(this.elementName)
    }
  }
}

export default  {
  name: 'ButtonElement',

  data () {
    return {
      elementName: 'Button',
      showEditor: false,
      editor: null
    }
  },
  
  methods: {
    initEditor () {
      this.showEditor = true
      this.editor = new Editor(this.elementName)
    }
  }
}

Komponennya berbeda, tetapi memiliki logika yang sama. Untuk membuatnya, Anda harus membuat file js biasa. Adalah logis untuk menempatkannya di direktori mixins di sebelah komponen.

// mixin.js
export default  {
  data () {
    return {
      showEditor: false,
      editor: null
    }
  },
  
  methods: {
    initEditor () {
      this.showEditor = true
      this.editor = new Editor(this.elementName)
    }
  }
}

// TextElement.vue
import mixin from './mixins/mixin'

export default  {
  name: 'TextElement',

  mixins: [mixin]  //  

  data () {
    return {
      elementName: 'Text',
    }
  },
}

// ButtonElement.vue
import mixin from './mixins/mixin'

export default  {
  name: 'ButtonElement',

  mixins: [mixin]

  data () {
    return {
      elementName: 'Button'
    }
  }
}

Seperti yang Anda lihat dari contoh, hampir semua logika bermigrasi ke mixin. Saat menggunakan kotoran di dalam komponen, semua opsi mereka bergabung. Dan dalam komponen, Anda dapat dengan bebas memanggil metode initEditor () , dan, sebaliknya, dalam pengotor, elementName dari komponen digunakan di sini . Dalam hal ini, objek data akan digabungkan secara rekursif, dan properti dari komponen akan diutamakan.

Jadi, manfaat dari pengotor jelas - ini adalah penggunaan kembali kode. Tapi ada yang minus. Contoh ini adalah sintetis, hanya beberapa baris. Komponen nyata, seperti yang digunakan dalam Ptah, dapat ditulis dalam beberapa ratus baris kode. Tidak selalu jelas bagi orang yang belum menulis kode ini cara kerjanya, terutama jika dia mengabaikan penambahan mixin ke komponen. Sayangnya, menyingkirkan minus ini tidak akan berhasil. Saya dapat merekomendasikan dua hal: jelaskan pengoperasian komponen di JSDoc dan gunakan nama khusus untuk properti dari pengotor (misalnya, Anda dapat menambahkan awalan, yang akan Anda sepakati bersama tim sebelumnya).

Sediakan / Suntikkan


Sepasang opsi ini selalu digunakan bersama dan memungkinkan Anda untuk mentransfer data dari komponen induk ke seluruh hierarki turunannya. Opsi-opsi ini terutama digunakan untuk menulis plugin, dokumentasi resmi tidak merekomendasikan menggunakannya dalam aplikasi. Dalam aplikasi, komunikasi antar komponen dibangun dengan sangat baik di Vuex. Namun, fungsi ini masih patut mendapat perhatian.

Bagaimana itu bekerja?


Pertama, kita perlu mendefinisikan data dalam komponen induk, yang akan kita sampaikan kepada turunannya.

// Parent.vue        
export default {
  provide: {
   device: 'is-desktop'
  }
}

Sekarang data yang ditransfer perlu tertanam dalam komponen anak.

// Child.vue    
export default {
  inject: ['device'],

  created () {
   console.log(this.device) // => "is-desktop"
  }
}

Seperti yang dapat Anda lihat dari contoh, semuanya cukup sederhana. Tetapi satu minus signifikan harus dicatat - data dari bundel persediaan / injeksi tidak reaktif secara default! Namun, kelemahan ini mudah dielakkan menggunakan Object.defineProperty :

provide () {
 let device = {}
 Object.defineProperty(device, 'type', { enumerable: true, get: () => this.device })
 return { device }
},

data () {
 return {
   device: 'is-desktop'
 }
}

Sekarang, mengubah perangkat ini di induk akan mengubahnya di keturunan.

Komponen Meta


Ada beberapa situasi ketika tidak diketahui sebelumnya komponen mana yang akan digunakan dalam kode. Pertimbangkan contoh dari editor kami. Tugasnya adalah sebagai berikut: di bagian bersyarat dari FirstScreen, perlihatkan Teks, Logo, elemen Tombol , lalu tambahkan SocialIcons ke elemen-elemen ini .

Jadi, jelas bahwa kita akan memiliki komponen bagian yang akan berfungsi sebagai wadah untuk elemen dan 4 komponen untuk elemen itu sendiri. Strukturnya akan kira-kira sebagai berikut:

/ sections
 -- FirstScreen.vue
/ elements
 -- Text.vue
 -- Logo.vue
 -- Button.vue
 -- SocialIcons.vue

Untuk menambahkan semua komponen elemen ke template FirstScreen sekaligus, dan kemudian beralih menggunakan kondisi akan menjadi keputusan yang sangat tidak bijaksana. Ada alat sederhana dan luar biasa untuk tugas-tugas seperti itu:

<component :is="%componentName%"/>

Elemen komponen dengan atribut : is , yang hanya menulis nama komponen. Dan terima kasih kepadanya, tugas kami diselesaikan:

<script>
export default  {
  name: 'FirstScreen',

  data () {
    return {
      elements: [
        'Text',
        'Logo',
        'Button',
      ],
    }
  }
}
</script>

<template>
  <div class="first-screen">
    <component v-for="element in elements" :is="element"/>
  </div>
</template>

Dalam array elemen , kami menulis nama-nama komponen dan kemudian hanya menampilkan komponen-komponen ini dalam satu lingkaran di dalam template FirstScreen . Sekarang, untuk menambahkan elemen dengan ikon jejaring sosial ke bagian kami, kami hanya perlu menjalankan this.elements.push ('SocialIcons') .

All Articles