SoFunction
Updated on 2025-04-07

Vue trick you don't know - develop a component that can be called through a method (recommended)

As the hottest front-end framework recently, Vue's simple way of getting started and powerful APIs are its advantages. At the same time, because of the diversity and richness of its APIs, many of its development methods are different from all component-based React. If you do not have a comprehensive understanding of Vue's API (some of which are not even mentioned in the documentation), you may go around a big circle when developing and designing a component. So I highly recommend that you first have an understanding of all the APIs in Vue when learning Vue.

For example, notification component notification is basically a standard configuration for modern web development and can be used in many places. In the front-end project with Vue as the core framework, since Vue itself is a componentized and virtual Dom framework, it is of course very simple to implement the display of a notification component. However, due to the usage characteristics of notification components, it is obviously inconvenient to write components directly in the template and control the display of notification components through v-show or props. Moreover, if notifications are to be used in action or other non-component scenarios, the usage of pure component mode cannot be achieved. So is there a way to use the Vue componentization feature to facilitate the display of a notification component, and to display notifications through a simple method call? This article is about this implementation method.

Target

Implement a Vue notification component that can be called directly within the component
Calling the notification component through method calls, such as Vue.$notify({...options})
Combining the above two methods, reuse the code

Implement notification components

This step is very simple. I believe that students who have done some Vue development can write a decent notification component. I won't go into details here, just add the code.

<template>
 <transition name="fade" @after-leave="afterLeave" @after-enter="setHeight">
  <div
   v-show="visible"
   :class="['notification']"
   :style="style"
   @mouseenter="clearTimer"
   @mouseleave="createTimer"
  >
   <span class="content">{{content}}</span>
   <a class="btn" @click="handleClose">{{btn || 'closure'}}</a>
  </div>
 </transition>
</template>

<script>
export default {
 name: 'Notification',
 props: {
  content: {
   type: String,
   default: ''
  },
  btn: {
   type: String,
   default: ''
  }
 },
 data () {
  return {
   visible: true
  }
 },
 computed: {
  style () {
   return {}
  }
 },
 methods: {
  handleClose (e) {
   ()
   ()
  },
  doClose () {
    = false
   this.$emit('close')
  },
  afterLeave () {
   this.$emit('closed')
  },
  clearTimer () {},
  createTimer () {},
  setHeight () {}
 }
}
</script>


<style lang="stylus" scoped>
.notification
 display: flex
 background-color #303030
 color rgba(255, 255, 255, 1)
 align-items center
 padding 20px
 position fixed
 min-width 280px
 box-shadow 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12)
 flex-wrap wrap
 transition all .3s
.content
 padding 0
.btn
 color #ff4081
 padding-left 24px
 margin-left auto
 cursor pointer
</style>

It should be noted here that we have defined a computed property called style, three methods, clearTimer, createTimer, and setHeight, but their content is all empty. Although it is useful on the template, it seems meaningless. When we want to extend the component later, I will talk about why we do this.

After creating this component, we can use <notification btn="xxx" content="xxx" /> in the template

Implement the notification component by calling the method

Inheriting components

Before implementing method calls, we need to extend this component, because these properties alone are not enough for us to use. When using method calls, we need to consider several issues:

  1. Display notification positioning
  2. Control of the occurrence and automatic disappearance of components
  3. How to type multiple notifications in succession

Under this premise, we need to extend the component, but these properties of the extension cannot be placed directly in the original component, because these may affect the use of the component in the template. What should we do? At this time, we need to use a very useful API in Vue, extend, and use it to inherit the properties of the original component and extend it.

Let’s look at the code first and create a file called, with the following content:

import Notification from './'

export default {
 extends: Notification,
 computed: {
  style () {
   return {
    position: 'fixed',
    right: '20px',
    bottom: `${ + 20}px`
   }
  }
 },
 data () {
  return {
   verticalOffset: 0,
   visible: false,
   height: 0,
   autoClose: 3000
  }
 },
 mounted () {
  ()
 },
 methods: {
  createTimer () {
   if () {
     = setTimeout(() => {
     ()
    }, )
   }
  },
  clearTimer () {
   if () {
    clearTimeout()
   }
  },
  setHeight () {
    = this.$
  }
 }
}

We can see that several methods that were previously implemented were implemented here, so why should we add the definition of those methods on the original component? Because it needs to be bound on the template, and the template cannot be extended, it can only be overwritten. If you want to overwrite and re-implement, the significance of the extension is not very big. Of course, students can make their own choices.

Pay attention to the following two points when using extend:

  1. Methods and attribute definitions are directly overridden
  2. The life cycle method is similar to Yumixin, and will be merged, that is, the original component and the inherited component will be called, and the original component will be called first.

Call this component through a method

Finally, what we need to do is to call this inherited component through the method. Let’s first look at the implementation of the source code:

// 
import Vue from 'vue'
import Component from './fun-component'
const NotificationConstructor = (Component)

const instances = []
let seed = 1

const removeInstance = (instance) => {
 const len = 
 if (!instance) return
 const index = (inst =>  === )

 (index, 1)

 if (len <= 1) return
 const removedHeight = 
 for (let i = index; i < len - 1; i++) {
  instances[i].verticalOffset =
   parseInt(instances[i].verticalOffset) - removedHeight - 16
 }
}

const notify = function (options) {
 const {
  onClose,
  ...rest
 } = options
 if (.$isServer) return
 options = options || {}
 const id = `notification_${seed++}`

 const instance = new NotificationConstructor({
  propsData: {
   ...rest
  }
 })

  = id
  = instance.$mount()
 (.$el)
  = true

 let verticalOffset = 0
 (item => {
  verticalOffset += item.$ + 16
 })
 verticalOffset += 16
  = verticalOffset
 (instance)
 .$on('closed', () => {
  if (typeof onClose === 'function') {
   onClose(instance)
  }
  removeInstance(instance)
  .$destroy()
 })
 return 
}

export default notify

First, through const NotificationConstructor = (Component), we get a subclass similar to Vue, and we can create an instance of Vue through new NotificationConstructor({...options}). At the same time, the instances created through this method have all the properties in the component definition.

After creating an instance, you can manually mount the component to the DOM through instance.$mount(), so that we can output DOM fragments without relying on the Vue component tree, achieving the effect of freely displaying notifications.

The implementation in the middle is mainly to maintain a notification array, push it in when it is created, and delete it when it disappears. This process does not stipulate that it must be implemented in this way. I will not elaborate on it, so as not to limit everyone's ideas. You can implement it according to your own ideas.

Use this method

To use this notification method, we can directly import the file, for example:

import notify from './'

notify({
 content: 'xxx',
 btn: 'xxx'
})

Of course, many of our scenarios are called internally in the component. In order to facilitate use within the component, we do not need to import each time. We can wrap this method into a Vue plug-in. We create one with the following content:

import Notification from './'
import notify from './function'

export default (Vue) => {
 (, Notification)
 .$notify = notify
  = notify
}

Then within the project, we can use:

import notify from '/path/to/notification/module'

(notify)

In this way, you can call notifications directly in the component through this.$notify({...options}), and you can also call them in other environments through ({...options}). You can try it in your own project.

Summarize

At this point, it's almost done about how to implement the content of calling a Vue component through a method. The Vue technical points we are involved here are as follows:

  1. Extend components through extend configuration
  2. Create a Vue subclass to create a Vue instance dynamically
  3. Actively mount component content to DOM through Vue instance

Vue has a lot of APIs. If you have not systematically learned the core knowledge and APIs of Vue before using Vue, you may not know that there is such an implementation method at all. Therefore, if you want to learn Vue well, the system must learn the core of Vue.

The above is the Vue technique that the editor introduces to you that you don’t know - to develop a component that can be explained and integrated through method calls. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support for my website!