ホームページ > ウェブフロントエンド > jsチュートリアル > Vue プラグインの書き方 vue.js サンプルチュートリアル

Vue プラグインの書き方 vue.js サンプルチュートリアル

小云云
リリース: 2017-12-12 15:09:03
オリジナル
2191 人が閲覧しました

この記事では主に vue プラグインの作成方法について説明します。学習する前に、なぜ vue プラグインを作成するのかを自問してください。

プロジェクト、特に大規模なプロジェクトでは、アニメーションやポップアップボックスの読み込みなど、再利用する必要がある部分がたくさんあります。一つ一つ参照するのは少々面倒ですし、vueファイル内で参照するコンポーネントが多すぎるとコードが肥大化してしまうため、vueプラグインをカプセル化する必要があります。

要件について話した後、具体的な実装を見てみましょう。現在、2種類のプラグインの書き方を試してみたので、一つずつ紹介していきます。

これは私のプロジェクトのディレクトリです。大まかな構造をできるだけシンプルに、わかりやすく説明します。

1 つは読み込みプラグインで、もう 1 つはトースト プラグインです。違いは、読み込みプラグインがコンポーネントとして導入されるのに対し、トースト プラグインはマウント ポイントに直接追加されて呼び出されることです。メソッドのステータスを変更します。

現在使用しているのは Jiangzi です:

トーストプラグイン

トーストファイルの下に 2 つのファイルがあります。接尾辞 vue が付いたファイルがプラグインのスケルトンです。js ファイルはこのスケルトンを配置します。を Vue グローバルに書き込み、動作ロジックを書き留めます。

toast.vue の内容を見てみましょう:


<template>
 <transition name="fade">
  <p v-show="show">
   {{message}}
  </p>

 </transition>
</template>

<script>
export default {
 data() {
 return {
  show: false,
  message: ""
 };
 }
};
</script>

<style lang="scss" scoped>
.toast {
 position: fixed;
 top: 40%;
 left: 50%;
 margin-left: -15vw;
 padding: 2vw;
 width: 30vw;
 font-size: 4vw;
 color: #fff;
 text-align: center;
 background-color: rgba(0, 0, 0, 0.8);
 border-radius: 5vw;
 z-index: 999;
}

.fade-enter-active,
.fade-leave-active {
 transition: 0.3s ease-out;
}
.fade-enter {
 opacity: 0;
 transform: scale(1.2);
}
.fade-leave-to {
 opacity: 0;
 transform: scale(0.8);
}
</style>
ログイン後にコピー


主な内容は 2 つだけで、show を表示するかどうかとどの内容を表示するかを決定します。 メッセージを表示します。 show和显示什么内容的message

粗看这里,有没有发现什么问题?

这个文件中并没有props属性,也就是无论是show也好,message也好,就没有办法通过父子组件通信的方式进行修改,那他们是怎么正确处理的呢。别急,来看他的配置文件。

index.js:


import ToastComponent from &#39;./toast.vue&#39;

const Toast = {};

// 注册Toast
Toast.install = function (Vue) {
 // 生成一个Vue的子类
 // 同时这个子类也就是组件
 const ToastConstructor = Vue.extend(ToastComponent)
 // 生成一个该子类的实例
 const instance = new ToastConstructor();

 // 将这个实例挂载在我创建的p上
 // 并将此p加入全局挂载点内部
 instance.$mount(document.createElement(&#39;p&#39;))
 document.body.appendChild(instance.$el)
 
 // 通过Vue的原型注册一个方法
 // 让所有实例共享这个方法 
 Vue.prototype.$toast = (msg, duration = 2000) => {
  instance.message = msg;
  instance.show = true;

  setTimeout(() => {
   
   instance.show = false;
  }, duration);
 }
}

export default Toast
ログイン後にコピー


这里的逻辑大致可以分成这么几步:

创建一个空对象,这个对象就是日后要使用到的插件的名字。此外,这个对象中要有一个install的函数。使用vue的extend方法创建一个插件的构造函数(可以看做创建了一个vue的子类),实例化该子类,之后的所有操作都可以通过这个子类完成。之后再Vue的原型上添加一个共用的方法。

这里需要着重提的是Vue.extend()。举个例子,我们日常使用vue编写组件是这个样子的:


Vue.component(&#39;MyComponent&#39;,{
 template:&#39;<p>这是组件</p>&#39;
})
ログイン後にコピー


这是全局组件的注册方法,但其实这是一个语法糖,真正的运行过程是这样的:


let component = Vue.extend({
 template:&#39;<p>这是组件</p>&#39;
})

Vue.component(&#39;MyComponent&#39;,component)
ログイン後にコピー


Vue.extend会返回一个对象,按照大多数资料上提及的,也可以说是返回一个Vue的子类,既然是子类,就没有办法直接通过他使用Vue原型上的方法,所以需要new一个实例出来使用。

在代码里console.log(instance)

得出的是这样的结果:

可以看到$el:p.toast

也就是toast组件模板的根节点。

疑惑的是,我不知道为什么要创建一个空的p节点,并把这个实例挂载在上面。我尝试注释这段代码,但是运行会报错。

查找这个错误的原因,貌似是因为


document.body.appendChild(instance.$el)
ログイン後にコピー


这里面的instance.$el的问题,那好,我们console下这个看看。WTF!!!!结果居然是undefined

ここをざっと見て、何か問題は見つかりましたか?

このファイルには props 属性がありません。つまり、show であろうと message であろうと、親子コンポーネント通信を通じてそれを変更する方法はありません。では、どうすればそれを正しく処理できるのでしょうか。心配しないで、設定ファイルを見てみましょう。


index.js:


console.log(instance)
ログイン後にコピー

ここでのロジックは、次のステップに大まかに分けることができます:

で使用されるプラグインの名前である空のオブジェクトを作成します。未来。さらに、このオブジェクトにはインストール関数が必要です。 vue の extend メソッドを使用して、プラグイン コンストラクター (vue のサブクラスの作成と見なされます) を作成し、サブクラスをインスタンス化し、後続のすべての操作をこのサブクラスを通じて完了できます。次に、共有メソッドを Vue プロトタイプに追加します。

ここで言及する必要があるのは、Vue.extend() です。たとえば、コンポーネントを作成するための vue の日常的な使用方法は次のようになります。


instance.$mount(document.createElement(&#39;p&#39;))
ログイン後にコピー


これはグローバルコンポーネントの登録メソッドですが、実際には構文上の糖衣です。実際の実行プロセスは次のとおりです。 :


instance.$mount(instance.$el)
ログイン後にコピー

Vue.extend は、ほとんどの情報によると、Vue のサブクラスを返すとも言えます。これは、サブクラスであるため、それを渡す方法はありません。 Vue プロトタイプのメソッドを直接使用するため、それを使用するには新しいインスタンスが必要です。

コード console.log(instance) の結果は次のようになります:


トースト コンポーネント テンプレートのルート ノードである $el:p.toast


が確認できます。

混乱しているのは、なぜ空の p ノードを作成し、その上にこのインスタンスをマウントする必要があるのか​​がわからないことです。このコードをコメントしようとしましたが、実行するとエラーが発生します。

このエラーの理由を見つけてください。それは


import Vue from &#39;vue&#39;
import App from &#39;./App&#39;
// import router from &#39;./router&#39;
import Toast from &#39;./components/taost&#39;
Vue.use(Toast)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({

 // router,
 render: h => h(App)
}).$mount(&#39;#app&#39;)
ログイン後にコピー


🎜🎜 instance.$el に問題があるからです。これを慰めて見てみましょう。なんと! ! ! !結果は 未定義 であることが判明しました。 🎜🎜それでは🎜🎜🎜🎜
// app.vue
<template>
 <p id="app">
 <loading duration=&#39;2s&#39; :isshow=&#39;show&#39;></loading>
 <!-- <button @click="show = !show">显示/隐藏loading</button> -->
 <button @click="toast">显示taost弹出框</button>
 </p>
</template>

<script>
export default {
 name: "app",
 data() {
 return {
  show: false
 };
 },
 methods: {
 toast() {
  this.$toast("你好");
 }
 }
};
</script>

<style>
#app {
 font-family: "Avenir", Helvetica, Arial, sans-serif;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 text-align: center;
 color: #2c3e50;
 margin-top: 60px;
}
</style>
ログイン後にコピー
🎜🎜🎜🎜🎜🎜🎜🎜🎜を前の写真と比べてみましょう。はい、つまり、🎜🎜🎜🎜
<template>
 <p class=&#39;wrapper&#39; v-if="isshow">
  <p class=&#39;loading&#39;>
   <img src="./loading.gif">
  </p>
 </p>
</template>

<script>
export default {
 props: {
 duration: {
  type: String,
  default: "1s" //默认1s
 },
 isshow: {
  type: Boolean,
  default: false
 }
 },
 data: function() {
 return {};
 }
};
</script>

<style lang="scss" scoped>

</style>
ログイン後にコピー
ログイン後にコピー
🎜🎜🎜🎜🎜🎜という文をコメントした後、マウントポイントは存在しなくなりました。それから私はこの文を変更しようとしました: 🎜🎜🎜🎜
import LoadingComponent from &#39;./loading.vue&#39;

let Loading = {};

Loading.install = (Vue) => {
 Vue.component(&#39;loading&#39;, LoadingComponent)
}

export default Loading;
ログイン後にコピー
ログイン後にコピー
🎜🎜🎜🎜 🎜🎜$elは魔法のように再び戻ってきました...走ってください。ただし、いずれの場合も、これは、後続の操作のためにインスタンスをノードにマウントする必要があることを意味します。 🎜🎜その後のコードは、Vue プロトタイプにプラグインの状態を変更するメソッドを追加するだけです。次に、このオブジェクトをエクスポートします。 🎜🎜次のステップは使い方です。 main.js がどのように書かれているかを見てみましょう: 🎜🎜🎜🎜
// main.js
import Vue from 'vue'
import App from './App'
// import router from './router'
import Toast from './components/taost'
import Loading from './components/loading'

Vue.use(Toast)

Vue.use(Loading)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({

 // router,
 render: h => h(App)
}).$mount('#app')

// app.vue
<template>
 <p id="app">
 <loading duration=&#39;2s&#39; :isshow=&#39;show&#39;></loading>
 <!-- <button @click="show = !show">显示/隐藏loading</button> -->
 <button @click="toast">显示taost弹出框</button>
 </p>
</template>

<script>
export default {
 name: "app",
 data() {
 return {
  show: false
 };
 },
 methods: {
 toast() {
  this.$toast("你好");
 }
 }
};
</script>

<style>
#app {
 font-family: "Avenir", Helvetica, Arial, sans-serif;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 text-align: center;
 color: #2c3e50;
 margin-top: 60px;
}
</style>
ログイン後にコピー
ログイン後にコピー
🎜🎜🎜🎜🎜🎜 この方法では、次のように他の vue ファイルで直接使用できます: 🎜🎜🎜🎜
vue.use(toast)
ログイン後にコピー
ログイン後にコピー
🎜🎜🎜🎜🎜🎜

通过在methods中增加一个方法控制写在Vue原型上的$toast对toast组件进行操作。

这样toast组件的编写过程就结束了,可以看到一开始gif图里的效果。

loading插件

经过上一个插件的讲解,这一部分就不会那么细致了,毕竟大多数都没有什么不同,我只指出不一样的地方。


<template>
 <p class=&#39;wrapper&#39; v-if="isshow">
  <p class=&#39;loading&#39;>
   <img src="./loading.gif">
  </p>
 </p>
</template>

<script>
export default {
 props: {
 duration: {
  type: String,
  default: "1s" //默认1s
 },
 isshow: {
  type: Boolean,
  default: false
 }
 },
 data: function() {
 return {};
 }
};
</script>

<style lang="scss" scoped>

</style>
ログイン後にコピー
ログイン後にコピー



这个就只是一个模板,传入两个父组件的数据控制显示效果。

那再来看一下该插件的配置文件:


import LoadingComponent from &#39;./loading.vue&#39;

let Loading = {};

Loading.install = (Vue) => {
 Vue.component(&#39;loading&#39;, LoadingComponent)
}

export default Loading;
ログイン後にコピー
ログイン後にコピー



这个和taoat的插件相比,简单了很多,依然是一个空对象,里面有一个install方法,然后在全局注册了一个组件。

比较

那介绍了这两种不同的插件编写方法,貌似没有什么不一样啊,真的是这样么?

来看一下完整的main.js和app.vue这两个文件:


// main.js
import Vue from 'vue'
import App from './App'
// import router from './router'
import Toast from './components/taost'
import Loading from './components/loading'

Vue.use(Toast)

Vue.use(Loading)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({

 // router,
 render: h => h(App)
}).$mount('#app')

// app.vue
<template>
 <p id="app">
 <loading duration=&#39;2s&#39; :isshow=&#39;show&#39;></loading>
 <!-- <button @click="show = !show">显示/隐藏loading</button> -->
 <button @click="toast">显示taost弹出框</button>
 </p>
</template>

<script>
export default {
 name: "app",
 data() {
 return {
  show: false
 };
 },
 methods: {
 toast() {
  this.$toast("你好");
 }
 }
};
</script>

<style>
#app {
 font-family: "Avenir", Helvetica, Arial, sans-serif;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 text-align: center;
 color: #2c3e50;
 margin-top: 60px;
}
</style>
ログイン後にコピー
ログイン後にコピー



可以看出来,loading是显示的写在app.vue模板里的,而toast并没有作为一个组件写入,仅仅是通过一个方法控制显示。

来看一下html结构和vue工具给出的结构:

看出来了么,toast插件没有在挂载点里面,而是独立存在的,也就是说当执行


vue.use(toast)
ログイン後にコピー
ログイン後にコピー


相关推荐:

vue组件的3种书写形式详解

实用的vue.js项目中小技巧汇总

Vue.js划分组件的实现方法介绍

以上がVue プラグインの書き方 vue.js サンプルチュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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