Purpose, in fact, in order to use the js way to call popover

The purpose of a plug-in is to invoke the pop-up component in js fashion. Custom content. Don’t worry about the code in popover use. No need to write popover HTML code. This is a simple popover call, custom slot contents, configurable parameters, and event callbacks.

  methods:{
        openDialog(){
            this.$Modal({
                // The popover contains nested components
                component: xxx,
                // Nested components pass properties
                componentProps: {},// Popover property Settings
                props: {},// Event callback
                methods: {}}); }}Copy the code

Writing in the front

The application Element – UI is mostly used in real development scenarios. So the plug-in takes el-Dialog as an example. In theory, it can be extended to any UI component library related popover business, here we can draw inferinferies.

This article is for technology sharing, achievement sharing, if there is a need to forward use, please bring the original link. Thank you ~ if there is a better way to welcome communication ~ finally, is to write the original intention of the document is actually very simple, is for your thumbs up

Start your little hands

Daily development status.

  • Redundant code

Multiple popovers need to be defined and multiple properties need to be defined. And set these properties to true or false during business use.

  • Poor reusability

Pages have a lot more non-business logic control code (less readable). For example, the control code will be written to the parent page of the first shell when the second shell is opened inside the first shell.

  • Poor maintainability

Irrelevant code interspersed in the business process, poor decoupling. Maintenance is also relatively demanding. You need to look up the properties that control whether the popover displays or not. Centuries have passed

Component development or as far as possible decoupling. Let the use of arbitrary. Business code is more independent. Component reusability is all improved.

In everyday coding

When the business needs more than one popover when the basic is as follows, barabara coding… Of course, there may be other encapsulation methods used. But simply write properties that control whether the popovers are visible or not and how parameters are passed to child components. The second is that the child component business process is completed to call back, etc. These seemingly tedious but seemingly necessary things. Writing like this is a little bit not pretty (actually lazy, don’t want to write so much code. Simple is good, minimalism is better)

<template>
    / /... For example - balla balla some popover code.........
    <el-dialog
      title="Basic Vehicle Information"
      width="50%"
      append-to-body
      destroy-on-close
      :visible="carInfoVisible"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :before-close="closeCarInfo"
    >
      <info
        v-if="carInfoVisible"
        :info-id="infoId"
        :car-info-visible="carInfoVisible"
        @close="closeCarInfo"
      />
    </el-dialog>
    
    <el-dialog
      title="Vehicle Operation Information"
      width="50%"
      append-to-body
      destroy-on-close
      :visible="carInfoWorkVisible"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :before-close="closeCarWork"
    >
      <work
        v-if="carInfoWorkVisible"
        :info-id="infoId"
        :car-info-visible="carInfoWorkVisible"
        @close="closeCarWork"
      />
    </el-dialog>
  / /... If there is any other business you need to repeat ++.........
</template>


export default {
    data(){
        return {
            closeCarInfo:false.carInfoWorkVisible:false. A little... }},methods: {... A little bit of popover component event callback...closeCarWork(){}}}Copy the code

Lazy cancer sets in and starts thinking

Can these cookie-cutter things be optimized? If you use popovers of JS calls, you should save some code. Then it would be nice if the contents of the popover could be passed by themselves.

  • You don’t just want to control whether pop-ups are displayed or not and pass parameters. Make variables in data really big.
  • The content component of each popover page is arbitrary and easy to use. Parameter passing and event callbacks are simple and self-definable.

Inspired, other component library JS calls look like this

  methods:{
        openDialog(){
            this.$Modal({
                title: 'Js'.content: 'This is a popup with a Js call'}); }}Copy the code

And this is what I expected.

  • Popover properties can be set
  • Make it easy to customize popover nested components
  • You can set the transfer properties of custom popover nested components
  • You can set event callbacks for custom popover nested components
  methods:{
        openDialog(){
            this.$Modal({
                // The popover contains nested components
                component: xxx,
                // Nested components pass properties
                componentProps: {},// Popover property Settings
                props: {},// Event callback
                methods: {}}); }}Copy the code

Implementation approach

We instantiate an El-Dialog component and set the default slots of El-Dialog each time we use the call. Consider peer use and nested use. So when you instantiate a component, you createElement a div. Elements mounted as components. And put the element in the body. So the code should look something like this.

import Vue from 'vue'
let instance

const Modal = function ({ component, methods, props, componentProps }) {
  const dom = document.createElement('div')
  document.body.appendChild(dom)
  instance = new Vue({
      el: dom,
  })
}
export default Modal
Copy the code

So how to render the popover and define the popover nested components?

Scheme 1 Template template rendering method (GG)

That’s the way it started. Balabalcoding… The following

import Vue from 'vue'
import { Dialog } from 'element-ui'

let instance

const template =
    '
      
       '
       +
        '<Plugin v-on:close="close" :componentProps="componentProps"> </Plugin>' +
    '</Dialog>'

const Modal = function ({ component, methods, props, componentProps }) {
  const dom = document.createElement('div')
  document.body.appendChild(dom)
  instance = new Vue({
      el: dom,
      template,
      components: {
       Dialog: Dialog,
       Plugin: component
      },
      data() {
          return {
              title:'Popover description Title'.showModal:true. It's not flexible if there are more parameters... }},methods: {
        close(){
            this.showModal = false}}})return instance
}
export default Modal
Copy the code

After some debugging, I found that the scheme was not very good. Compile warnings and handle warnings in real time. If you have multi-parameter passing, the follow-up is also a disaster. So this is where I end up. If there are students who can complete the verification, please leave a message to inform us.

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
Copy the code

Scheme 2 render function render way

Render due to its own use of relatively less. It is simple to use, just render as a single label. Plus the way of writing a little uncomfortable, has been ignored when the general. Component rendering wasn’t even considered. The first argument to createElement supports the component option object !!!! . That means you can render components. biubiu coding… Wait a minute, in that way how do you determine the content component of the popover? We all know that the contents of an El-Dialog are inserted through slot slots. Can Render set up slots? The answer is yes. By setting scopedSlots.

Click to learn more about the Render function.

// @returns {VNode}
createElement(
  // {String | Object | Function}
  // An HTML tag name, component option object, or
  Resolve an async function of any of the above. Required fields.
  'div'.// {Object}
  // A data object corresponding to the attribute in the template. Optional.
  {
    // (see next section for details)
  },

  // {String | Array}
  // Child virtual nodes (VNodes), built from 'createElement()',
  // You can also use strings to generate "text virtual nodes". Optional.
  [
    'Write some words first.',
    createElement('h1'.'A headline'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'}})])// Drill down into the data object
{
 // The format of the scope slot is
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props= > createElement('span', props.text)
  },
  // If the component is a child of another component, specify a name for the slot
  slot: 'name-of-slot',}Copy the code

After reviewing the render documentation. The final essence is to render– to make the template write.

import Vue from 'vue'
import { Dialog } from 'element-ui'
let instance

const Modal = function ({ component, methods, props, componentProps }) {
  const dom = document.createElement('div')
  document.body.appendChild(dom)
  instance = new vue({
    el: dom,
    data () {
      return {
        showModal: true}},components: {
      Dialog: Dialog,
      Plugin: component
    },
    render (createElement) {
      return createElement(
        'Dialog', {
          scopedSlots: {
            default: () = > createElement('Plugin')}})},})return instance
}

export default Modal

Copy the code

Finally adjust the passpropsBound to the callbackmethods. Components inside the popover. It doesn’t have to be pure all the time. Look at the popovervisible:trueRendering is available.renderCan render according to the data responsively. Set up thescopedSlotsRender at display time.

import Vue from 'vue'
import { Dialog } from 'element-ui'

let instance

const Modal = function ({ component, methods, props, componentProps }) {
  if (Vue.prototype.$isServer) return
  const dom = document.createElement('div')
  document.body.appendChild(dom)
  instance = new Vue({
    el: dom,
    data () {
      return {
        showModal: true}},components: {
      Dialog: Dialog,
      Plugin: component
    },
    render (createElement) {
      const plugin = this.showModal ? () = > createElement('Plugin', {
        props: {
          ...componentProps
        },
        on: {
          close: (e) = > this.close(e), ... methods } }) :null
      return createElement(
        'Dialog', {
          props: {
            visible: this.showModal, ... props },on: {
            close: (e) = > this.close(e)
          },
          scopedSlots: {
            default: plugin
          }
        })
    },
    methods: {
      close () {
        this.showModal = false
        document.body.removeChild(this.$el)
        this.$destroy()
      }
    }
  })
  return instance
}

export default Modal
Copy the code

The plug-in USES

It can be imported from main.js and loaded into the Prototype prototype.

  // main.js
  import modal from '@/plugins/modal'
  Vue.prototype.$modal = modal
  
  // Use pop-ups in js mode, configuration mode to complete parameter passing, event callback
   this.$modal({
    // Popover nested components pass properties
    componentProps: {
      id: '7676043D-F0DA-80DA-1CBD-BDD7068B3A77'
    },
    // The popover contains nested components
    // component: Table, // synchronize
    component: (resolve) = > require(['./cube-table-list.vue'], resolve), / / asynchronous
    // Popover property Settings
    props: {
      title: 'Basic Info popup'
      // width: '520px',
      // fullscreen: false
    },
    // Event callback
    methods: {
      refresh: (e) = > {
        console.log(e, '--x-x-x-')}}})Copy the code

Popovers are called as js.

Invoke the component as js. Determines popover content by configuration. You can omit some of these non-business and non-business attributes and methods. It doesn’t matter to our code whether popovers close or not. Call render when needed, destroy when closed. Support infinite pole nesting, multiple peer use. Let development focus more on business development.

// This is the code
<template>
    / /... For example - balla balla some popover code.........
    <el-dialog
      title="Basic Vehicle Information"
      width="50%"
      append-to-body
      destroy-on-close
      :visible="carInfoVisible"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :before-close="closeCarInfo"
    >
      <info
        v-if="carInfoVisible"
        :info-id="infoId"
        :car-info-visible="carInfoVisible"
        @close="closeCarInfo"
      />
    </el-dialog>
  / /... N++ popup window...
</template>

Copy the code

Use correspondence mapping.

In the final

This code plug-in is my original design, because before this also tried to find a similar solution. I haven’t found the right one. And then you have this article that you see. Of course, if there are similarities, right when I did not see ~.

This article is for technology sharing, achievement sharing, if there is a need to forward use, please bring the original link. Thank you ~ if there is a better way to welcome communication ~ finally, is to write the original intention of the document is actually very simple, is for your thumbs up

Start your little hands