ホームページ > ウェブフロントエンド > Vue.js > コンポーネントを呼び出す vuejs メソッド

コンポーネントを呼び出す vuejs メソッド

藏色散人
リリース: 2021-11-01 11:16:58
オリジナル
3488 人が閲覧しました

Vuejs によるコンポーネント呼び出し方法: 1. v-model または .sync を通じてコン​​ポーネントの表示と非表示を明示的に制御します; 2. js コードを通じて呼び出します; 3. Vue 命令を通じて呼び出します。

コンポーネントを呼び出す vuejs メソッド

この記事の動作環境: Windows7 システム、vue2.9.6 バージョン、DELL G3 コンピューター。

Vue コンポーネントの 3 つの呼び出しメソッド

最近 fj-service-system を書いているときにいくつかの問題に遭遇しました。つまり、ダイアログやメッセージなどの一部のコンポーネントについては、element-ui などのサードパーティ コンポーネント ライブラリを導入する必要があるのでしょうか、それとも自分で実装する必要があるのでしょうか?オンデマンドで導入する機能はありますが、全体的なスタイルが私のシステム全体と一致しません。したがって、これらの単純なコンポーネントを自分で手動で実装することを検討できます。

通常、Vue に関する記事を読むと、Vue の単一ファイル コンポーネントの開発ページについて書かれていることがほとんどです。単一コンポーネント開発に関する記事は比較的少ないです。 fj-service-system プロジェクトに取り組んでいたとき、単一コンポーネントの開発も非常に興味深いことに気づきました。書き留めて記録することができます。私が書いたものはUIフレームワークではなく単なる記録であり、githubリポジトリもないのでコードを見てみましょう。

    #v-model または .sync はコンポーネントの表示と非表示を明示的に制御します
  • js コードを介した呼び出し
  • Vue 命令を介した呼び出し
コンポーネントを書くとき、多くの書き方やインスピレーションは element-ui から得られます。ありがとうございます。

ダイアログ

私はこれをダイアログ ボックスと呼ぶことに慣れていますが、実際にはモーダル (ポップアップ ウィンドウ) コンポーネントとも呼ばれます。実際、ページ上に小さなウィンドウがポップアップし、この小さなウィンドウ内のコンテンツをカスタマイズできます。通常、ログイン機能のダイアログ ボックスとして使用できます。

この種のコンポーネントは、v-model または .sync を通じて表示と非表示を明示的に制御するのに非常に適しています。ページに直接記述して、データを通じて制御できます。これは、Vue の設計思想に最もよく適合するコンポーネントでもあります。

このために、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>
ログイン後にコピー
というコンポーネントを作成できます。

CSS などは書きません。コンポーネント自体とはほとんど関係ありません。ただし、上記の Dialog__wrapper クラスも全画面かつ透過的であることに注意してください。主にクリック イベントを取得し、クリック位置をロックするために使用されます。DOM の Node.contains() メソッドを使用して、クリックされたかどうかを判断します。半透明のモーダル レイヤーなど、ダイアログの外側をクリックすると、close イベントが送出され、ダイアログが閉じられます。

これを外部から呼び出したい場合は、次のように呼び出すことができます:

<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>
ログイン後にコピー

ダイアログの開閉をより魅力的にするには、

注意

このコンポーネントは、element-ui のメッセージ (メッセージ プロンプト) に似ています。最も魅力的なのは、v-model を通じてページ内のコンポーネントの HTML 構造を明示的に記述して呼び出すのではなく、js の this.$message() などのメソッドを使用して呼び出されることです。ただし、この方法は Vue のデータ駆動型の考え方に反します。しかし、状況によっては非常に便利だと言わざるを得ません。

Notice などのコンポーネントの場合、ユーザーに簡単なメッセージを提供するには、一度に数語のプロンプトを表示するだけで済みます。プロンプトが表示される情報はさまざまであり、プロンプトが重ねて表示される場合もあります。 1番目のメソッドで呼び出す場合は事前にhtmlの構造を書かなければならず、手間がかかるのは間違いなく、メッセージボックスの数も予測できません。 js メソッドを通じて呼び出す場合は、さまざまな状況で呼び出されるテキストと型を考慮するだけで済みます。

以前のアプローチは、Vue ファイルを作成し、components 属性を通じてページを導入し、タグ呼び出しを明示的に記述することでした。では、js メソッドを介してコンポーネントを呼び出すにはどうすればよいでしょうか?

ここで重要なのは、Vue の extend メソッドです。

このドキュメントでは、この方法で extend を使用する方法については詳しく説明されておらず、手動でマウントする必要がある Vue コンポーネント コンストラクターとしてのみ説明されています。

element-ui のソース コードを参照すると、上記の機能を実装する方法がわかります。

まず、 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>
ログイン後にコピー

上記の内容は、通常の単一ファイルの Vue コンポーネントとあまり変わりません。しかし、違いは小道具がないことです。では、このコンポーネントの可視性を外部から制御するにはどうすればよいでしょうか?

したがって、このコンポーネントを引き継いで extend メソッドを呼び出すには、js ファイルが必要です。同じディレクトリにindex.jsファイルを作成できます。

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上
  }
}
ログイン後にコピー

このファイルでは、 NoticeConstructor を通じて、js を通じてコン​​ポーネントのさまざまなプロパティを制御できることがわかります。最後に、これを Vue プロトタイプに登録します。これにより、ページ内で this.$notice() メソッドを使用できるようになり、このコンポーネントを簡単に呼び出して簡単な通知効果を作成できるようになります。

もちろん、これは Vue プラグインと同等であることを忘れないでください。したがって、メイン JS で Vue.use() メソッドを呼び出す必要があります。
// main.js

// ...
import Notice from &#39;notice/index.js&#39;

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 &#39;loading/index.js&#39;

Vue.use(Loading)

// ...
ログイン後にコピー

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

<p v-loading.fullscreen="loading" loading-text="正在加载中">
ログイン後にコピー

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

总结

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

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

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

以上がコンポーネントを呼び出す vuejs メソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
vue
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート