Rumah >hujung hadapan web >View.js >kaedah vuejs untuk memanggil komponen

kaedah vuejs untuk memanggil komponen

藏色散人
藏色散人asal
2021-11-01 11:16:583464semak imbas

Kaedah memanggil komponen dalam vuejs: 1. Kawal paparan dan penyembunyian komponen secara eksplisit melalui v-model atau .sync; 2. Panggil melalui kod js;

kaedah vuejs untuk memanggil komponen

Persekitaran pengendalian artikel ini: sistem Windows 7, vue versi 2.9.6, komputer DELL G3.

Tiga cara untuk memanggil komponen Vue

Semasa saya menulis fj-service-system baru-baru ini, saya menghadapi beberapa masalah. Iaitu, untuk beberapa komponen saya, seperti Dialog dan Mesej, patutkah saya memperkenalkan perpustakaan komponen pihak ketiga, seperti elemen-ui, atau patutkah saya melaksanakannya sendiri? Walaupun mereka mempunyai fungsi memperkenalkan atas permintaan, gaya keseluruhan tidak sepadan dengan sistem keseluruhan saya. Oleh itu, anda boleh mempertimbangkan untuk melaksanakan komponen mudah ini secara manual sendiri.

Biasanya apabila kita membaca beberapa artikel tentang Vue, perkara yang boleh kita lihat biasanya bercakap tentang halaman pembangunan komponen fail tunggal Vue. Terdapat sedikit artikel mengenai pembangunan komponen tunggal. Semasa saya mengusahakan projek sistem-perkhidmatan fj, saya mendapati pembangunan komponen tunggal juga sangat menarik. Anda boleh menulisnya dan merekodkannya. Kerana apa yang saya tulis bukan rangka kerja UI, ia hanyalah rekod. Tiada repositori github, jadi mari kita lihat kod tersebut.

  • v-model atau .sync mengawal paparan dan penyembunyian komponen secara eksplisit
  • Panggil melalui kod js
  • Arahan panggilan melalui Vue

Semasa menulis komponen, banyak kaedah penulisan dan inspirasi datang dari elemen-ui, terima kasih.

Dialog

Saya sudah biasa memanggil perkara ini sebagai kotak dialog Malah, ia juga dipanggil komponen modal (tetingkap timbul). Malah, tetingkap kecil muncul pada halaman, dan kandungan dalam tetingkap kecil ini boleh disesuaikan. Ia biasanya boleh digunakan sebagai kotak dialog untuk fungsi log masuk.

Komponen jenis ini sangat sesuai untuk mengawal penampilan dan kehilangan secara eksplisit melalui model v atau .sync. Ia boleh ditulis terus pada halaman dan kemudian dikawal melalui data - ini juga merupakan komponen yang paling sesuai dengan idea reka bentuk Vue.

Untuk ini, kita boleh menulis komponen yang dipanggil Dialog.vue

<template>
  <div class="dialog">
    <div class="dialog__wrapper" v-if="visble" @clcik="closeModal">
      <div class="dialog">
        <div class="dialog__header">
          <div class="dialog__title">{{ title }}</div>
        </div>
        <div class="dialog__body">
          <slot></slot>
        </div>
        <div class="dialog__footer">
          <slot name="footer"></slot>
        </div>
      </div>
    </div>
    <div class="modal" v-show="visible"></div>
  </div></template><script>
  export default {    name: &#39;dialog&#39;,    props: {      title: String,      visible: {        type: Boolean,        default: false
      }
    },    methods: {      close() {        this.$emit(&#39;update:visible&#39;, false) // 传递关闭事件
      },      closeModal(e) {        if (this.visible) {          document.querySelector(&#39;.dialog&#39;).contains(e.target) ? &#39;&#39; : this.close(); // 判断点击的落点在不在dialog对话框内,如果在对话框外就调用this.close()方法关闭对话框
        }
      }
    }
  }</script>

Kami tidak akan menulis CSS atau perkara lain, ia kurang berkaitan dengan komponen itu sendiri. Walau bagaimanapun, perlu diperhatikan bahawa kelas dialog__wrapper di atas juga adalah skrin penuh dan telus Ia digunakan terutamanya untuk mendapatkan peristiwa klik dan mengunci kedudukan klik Ia menggunakan kaedah Node.contains() DOM untuk menentukan sama ada klik position ialah dialog itu sendiri. Jika anda mengklik di luar dialog, seperti lapisan modal lut sinar, acara tutup akan dihantar untuk menutup dialog.

Apabila kita ingin memanggilnya secara luaran, kita boleh memanggilnya seperti berikut:

<template>
  <div class="xxx">
    <dialog :visible.sync="visible"></dialog> 
    <button @click="openDialog"></button>
  </div></template><script>
  import Dialog from &#39;Dialog&#39;
  export default {    components: {
      Dialog
    },    data() {      return {        visible: false
      }
    },    methods: {      openDialog() {        this.visible = true // 通过data显式控制dialog
      }
    }
  }</script>

Untuk menjadikan pembukaan dan penutupan Dialog kelihatan lebih baik, anda boleh cuba menambah aad18214fa6ac3925af16de82cb519adf16a5bf536802b29986da931aa0fd1a1 dan kesan peralihan, kesan peralihan mudah akan kelihatan hebat.

Notis

Komponen ini serupa dengan mesej elemen-ui (gesa mesej). Apa yang paling menarik perhatian saya ialah ia tidak dipanggil secara eksplisit menulis struktur HTML komponen dalam halaman melalui v-model, tetapi dengan menggunakan kaedah seperti ini.$message() dalam js dipanggil. Walaupun kaedah ini bertentangan dengan pemikiran berasaskan data Vue. Tetapi saya harus mengatakan bahawa ia sangat mudah dalam beberapa situasi.

Untuk komponen seperti Notis, anda hanya perlu menggesa beberapa perkataan pada satu masa untuk memberi pengguna mesej ringkas. Maklumat yang digesa mungkin berbeza-beza, malah mungkin terdapat gesaan bertindih. Jika anda memanggilnya melalui kaedah pertama, anda perlu menulis struktur html terlebih dahulu Ini sudah pasti pendekatan yang menyusahkan, dan adalah mustahil untuk meramalkan berapa banyak kotak mesej yang akan ada. Jika anda memanggilnya melalui kaedah js, anda hanya perlu mempertimbangkan teks dan jenis yang berbeza yang dipanggil dalam situasi yang berbeza.

Pendekatan sebelumnya ialah menulis fail Vue, kemudian memperkenalkan halaman melalui atribut komponen dan menulis panggilan teg secara eksplisit. Jadi bagaimana untuk memanggil komponen melalui kaedah js?

Kunci di sini ialah kaedah lanjutan Vue.

Dokumen tidak memberikan butiran tentang cara lanjutan boleh digunakan dengan cara ini. Ia hanya dijelaskan sebagai pembina komponen Vue yang memerlukan pemasangan manual.

Dengan melihat kod sumber elemen-ui, kita boleh memahami cara melaksanakan fungsi di atas.

Pertama, buat fail Notice.vue

<template>
  <div class="notice">
    <div class="content">
      {{ content }}    </div>
  </div></template><script>
  export default {    name: &#39;notice&#39;,
    data () {      return {        visible: false,        content: &#39;&#39;,        duration: 3000
      }
    },    methods: {      setTimer() {        setTimeout(() => {          this.close() // 3000ms之后调用关闭方法
        }, this.duration)
      },      close() {        this.visible = false
        setTimeout(() => {          this.$destroy(true)          this.$el.parentNode.removeChild(this.$el) // 从DOM里将这个组件移除
        }, 500)
      }
    },    mounted() {      this.setTimer() // 挂载的时候就开始计时,3000ms后消失
    }
  }</script>

Apa yang ditulis di atas tidak jauh berbeza dengan komponen Vue fail tunggal biasa. Tetapi perbezaannya ialah tiada prop, jadi bagaimana untuk mengawal keterlihatan komponen ini secara luaran?

Jadi fail js diperlukan untuk mengambil alih komponen ini dan memanggil kaedah lanjutan. Anda boleh mencipta fail index.js dalam direktori yang sama.

import Vue from &#39;vue&#39;const NoticeConstructor = Vue.extend(require(&#39;./Notice.vue&#39;)) // 直接将Vue组件作为Vue.extend的参数let nId = 1const Notice = (content) => {  let id = &#39;notice-&#39; + nId++  const NoticeInstance = new NoticeConstructor({    data: {      content: content
    }
  }) // 实例化一个带有content内容的Notice

  NoticeInstance.id = id
  NoticeInstance.vm = NoticeInstance.$mount() // 挂载但是并未插入dom,是一个完整的Vue实例
  NoticeInstance.vm.visible = true
  NoticeInstance.dom = NoticeInstance.vm.$el  document.body.appendChild(NoticeInstance.dom) // 将dom插入body
  NoticeInstance.dom.style.zIndex = nId + 1001 // 后插入的Notice组件z-index加一,保证能盖在之前的上面
  return NoticeInstance.vm
}export default {  install: Vue => {
    Vue.prototype.$notice = Notice // 将Notice组件暴露出去,并挂载在Vue的prototype上
  }
}

Dalam fail ini kita dapat melihat bahawa melalui NoticeConstructor kita boleh mengawal pelbagai sifat komponen melalui js. Akhir sekali, kami mendaftarkannya ke dalam prototaip Vue, supaya kami boleh menggunakan kaedah this.$notice() di dalam halaman, dan kami boleh memanggil komponen ini dengan mudah untuk menulis kesan pemberitahuan ringkas.

Sudah tentu, jangan lupa bahawa ini adalah bersamaan dengan pemalam Vue, jadi anda perlu memanggil kaedah Vue.use() dalam js utama:

// main.js

// ...
import Notice from 'notice/index.js'

Vue.use(Notice)

// ...

Loading

在看element-ui的时候,我也发现了一个很有意思的组件,是Loading,用于给一些需要加载数据等待的组件套上一层加载中的样式的。这个loading的调用方式,最方便的就是通过v-loading这个指令,通过赋值的true/false来控制Loading层的显隐。这样的调用方法当然也是很方便的。而且可以选择整个页面Loading或者某个组件Loading。这样的开发体验自然是很好的。

其实跟Notice的思路差不多,不过因为涉及到directive,所以在逻辑上会相对复杂一点。

平时如果不涉及Vue的directive的开发,可能是不会接触到modifiers、binding等概念。参考文档

简单说下,形如:v-loading.fullscreen="true"这句话,v-loading就是directive,fullscreen就是它的modifier,true就是binding的value值。所以,就是通过这样简单的一句话实现全屏的loading效果,并且当没有fullscreen修饰符的时候就是对拥有该指令的元素进行loading效果。组件通过binding的value值来控制loading的开启和关闭。(类似于v-model的效果)

其实loading也是一个实际的DOM节点,只不过要把它做成一个方便的指令还不是特别容易。

首先我们需要写一下loading的Vue组件。新建一个Loading.vue文件

<template>
  <transition
    name="loading"
  	@after-leave="handleAfterLeave">
    <div
      v-show="visible"
      class="loading-mask"
      :class={&#39;fullscreen&#39;: fullscreen}>
      <div class="loading">
        ...      </div>
      <div class="loading-text" v-if="text">
        {{ text }}      </div>
    </div>
  </transition></template><script>export default {  name: &#39;loading&#39;,
  data () {    return {      visible: true,      fullscreen: true,      text: null
    }
  },  methods: {    handleAfterLeave() {      this.$emit(&#39;after-leave&#39;);
    }
  }
}</script><style>.loading-mask{
  position: absolute; // 非全屏模式下,position是absolute
  z-index: 10000;
  background-color: rgba(255,235,215, .8);
  margin: 0;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  transition: opacity .3s;
}
.loading-mask.fullscreen{
  position: fixed; // 全屏模式下,position是fixed
}
// ...</style>

Loading关键是实现两个效果:

    1.全屏loading,此时可以通过插入body下,然后将Loading的position改为fixed,插入body实现。
    2.对所在的元素进行loading,此时需要对当前这个元素的的position修改:如果不是absolute的话,就将其修改为relatvie,并插入当前元素下。此时Loading的position就会相对于当前元素进行绝对定位了。
所以在当前目录下创建一个index.js的文件,用来声明我们的directive的逻辑。

import Vue from &#39;vue&#39;const LoadingConstructor = Vue.extend(require(&#39;./Loading.vue&#39;))export default {  install: Vue => {
    Vue.directive(&#39;loading&#39;, { // 指令的关键
      bind: (el, binding) => {        const loading = new LoadingConstructor({ // 实例化一个loading
          el: document.createElement(&#39;div&#39;),          data: {            text: el.getAttribute(&#39;loading-text&#39;), // 通过loading-text属性获取loading的文字
            fullscreen: !!binding.modifiers.fullscreen 
          }
        })
        el.instance = loading; // el.instance是个Vue实例
        el.loading = loading.$el; // el.loading的DOM元素是loading.$el
        el.loadingStyle = {};
        toggleLoading(el, binding);
      },      update: (el, binding) => {
        el.instance.setText(el.getAttribute(&#39;loading-text&#39;))        if(binding.oldValue !== binding.value) {
          toggleLoading(el, binding)
        }   
      },      unbind: (el, binding) => { // 解绑
        if(el.domInserted) {          if(binding.modifiers.fullscreen) {              document.body.removeChild(el.loading);
          }else {
            el.loading &&
            el.loading.parentNode &&
            el.loading.parentNode.removeChild(el.loading);
          }
        }
      }
    })    const toggleLoading = (el, binding) => { // 用于控制Loading的出现与消失
      if(binding.value) { 
        Vue.nextTick(() => {          if (binding.modifiers.fullscreen) { // 如果是全屏
            el.originalPosition = document.body.style.position;
            el.originalOverflow = document.body.style.overflow;
            insertDom(document.body, el, binding); // 插入dom
          } else {
            el.originalPosition = el.style.position;
            insertDom(el, el, binding); // 如果非全屏,插入元素自身
          }
        })
      } else {        if (el.domVisible) {
          el.instance.$on(&#39;after-leave&#39;, () => {
            el.domVisible = false;            if (binding.modifiers.fullscreen && el.originalOverflow !== &#39;hidden&#39;) {              document.body.style.overflow = el.originalOverflow;
            }            if (binding.modifiers.fullscreen) {              document.body.style.position = el.originalPosition;
            } else {
              el.style.position = el.originalPosition;
            }
          });
          el.instance.visible = false;
        }
      }
    }    const insertDom = (parent, el, binding) => { // 插入dom的逻辑
      if(!el.domVisible) {        Object.keys(el.loadingStyle).forEach(property => {
          el.loading.style[property] = el.loadingStyle[property];
        });        if(el.originalPosition !== &#39;absolute&#39;) {
          parent.style.position = &#39;relative&#39;
        }        if (binding.modifiers.fullscreen) {
          parent.style.overflow = &#39;hidden&#39;
        }
        el.domVisible = true;
        parent.appendChild(el.loading) // 插入的是el.loading而不是el本身
        Vue.nextTick(() => {
          el.instance.visible = true;
        });
        el.domInserted = true;
      }
    }
  }
}

同样,写完整个逻辑,我们需要将其注册到项目里的Vue下:

// main.js

// ...
import Loading from 'loading/index.js'

Vue.use(Loading)

// ...

至此我们已经可以使用形如

adb2c97e42ba7ef7e89c2223cc327580

这样的方式来实现调用一个loading组件了。

总结

在用Vue写我们的项目的时候,不管是写页面还是写形如这样的功能型组件,其实都是一件很有意思的事情。本文介绍的三种调用组件的方式,也是根据实际情况出发而实际操作、实现的。不同的组件通过不同的方式去调用,方便了开发人员,也能更好地对代码进行维护。当然也许还有其他的方式,我并没有了解,也欢迎大家在评论里指出!

最后再次感谢element-ui的源码给予的极大启发。

推荐:《最新的5个vue.js视频教程精选

Atas ialah kandungan terperinci kaedah vuejs untuk memanggil komponen. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn