Hand-in-hand teaches you a vue2.0 bullet window assembly

Hand-in-hand teaches you a vue2.0 bullet window assembly

Before you start, you need to know the pre-knowledge of developing vue plug-ins. It's recommended that you take a look at it first. Introduction of plug-ins for vue official website

Preview address http://haogewudi.me/kiko/inde...

Source address https://github.com/rascalHao/...

Construction project

  1. vue-cli initializes your vue project and builds vue init webpack my-project

  2. Usually the process of introducing plug-ins is:

    npm i <package> -S
    
    import Vue from 'vue'
    import xxx from 'xxx'
    Vue.use(xxx)
    

So you can create a new development directory under node_modules, which I call kiko.
So the steps to introduce our plug-ins are as follows (the project will eventually be built in the form of an npm package)

  import Vue from 'vue'
  import Kiko from '../node_modules/kiko/index.js'
  Vue.use(Kiko)
  1. Initialize a package.json file in your project directory by npm init command, specify your entry file index.js by default, and create a new index.js entry file in your project root directory.

  2. Here you build four types of pop-up window components (message, toolTip, confirm, load), the basic structure is shown in the figure.

Entry file (can be skipped first)

The plug-in for Vue.js should have a public method install. The first parameter of this method is the Vue constructor, and the second parameter is an optional option object; the plug-in is used through the global method Vue.use(); you can look at it again. Introduction of plug-ins for vue official website

    import KikoMessage from './packages/message/index.js'
    import KikoToolTip from './packages/tips/index.js'
    import KikoConfirm from './packages/confirm/index.js'
    import KikoLoading from './packages/loading/index.js'

    const install = function(Vue) {
      Vue.component(KikoMessage.name, KikoMessage)
      Vue.component(KikoToolTip.name, KikoToolTip)
      Vue.component(KikoConfirm.name, KikoConfirm)
      Vue.component(KikoLoading.name, KikoLoading)

      Vue.prototype.$kiko_tooltip = KikoToolTip.installToolTip
      Vue.prototype.$kiko_message = KikoMessage.installMessage
    }
    export default install

message

Create a message component in the project's root directory by

Vue.prototype.$kiko_message = function (methodOptions) {

// Logic...

}
To add the instance method global to call the message by calling this.$kiko_message()

  • message component structure

  • main.vue

    <template>
      <transition name="fade">
        <div class="kiko-message" v-if="isShow">
          {{message}}
        </div>
      </transition>
    </template>

    <script type="text/javascript">
      export default {
        name: 'kiko-message',
        data () {
          return {
            message: '',
            time: 3000,
            isShow: true
          }
        },
        mounted () {
          this.close()
        },
        methods: {
          close () {
            var that = this
            window.setTimeout(function() {
              that.isShow = false
            }, this.time);
          }
        }
      }
    </script>
  • index.js

    import Vue from 'vue'
    import Message from './src/main.vue'

    Message.installMessage = function(options) {
      if (options === undefined || options === null) {
        options = {
          message: ''
        }
      } else if (typeof options === 'string' || typeof options === 'number') {
        options = {
          message: options
        }
      }
      var message = Vue.extend(Message)

      var component = new message({
        data: options
      }).$mount()
      document.querySelector('body').appendChild(component.$el)
    }

    export default Message

When you get here, you can see the introduction of the entry file in front of you. You need to go through it. Vue.component Register as a component and bind the Message.installMessage method to Vue.prototype.$kiko_message.

toolTip

There is no choice to introduce toolTip by solidifying it in the page, because considering the possibility of introducing toolTip anywhere on the page, if solidified, it will greatly limit the use of toolTip scenarios. So a global method of this.$kiko_tooltip bound to Vue.prototype is used to trigger, so that you can customize the trigger mode, and you can automatically locate any element you need by passing in $event.

  • toolTip Component Structure

Same message component structure

  • main.vue

  <template>
    <div v-if="isShow" id="kiko_tool_tip" class="kiko-tool-tip" :class="{'left': direction === 'left', 'right': direction === 'right', 'top': direction === 'top', 'bottom': direction === 'bottom'}" :style="{'background-color': background, 'color': color, 'top': top, 'left': left}">
      {{content}}
      <div class="arrow" :style="arrowStyleObject"></div>
    </div>
  </template>

  <script type="text/javascript">
    export default {
      name: 'kikoToolTip',
      data () {
        return {
          isShow: true,
          time: 3000,
          content: '',
          direction: 'right',
          background: 'red',
          color: '#fff',
          arrowStyleObject: ''
        }
      },
      beforeMount () {
        let node = document.querySelector('#kiko_tool_tip')
        if (node && node.parentNode) {
          node.parentNode.removeChild(node)
        }
      },
      computed: {
        top () {
          switch (this.direction) {
            case 'top':
              return (this.rect.top - 12) + 'px'
            case 'bottom':
              return (this.rect.top + 12) + 'px'
            case 'left':
              return (this.rect.top + this.rect.height / 2) + 'px'
            case 'right':
              return (this.rect.top + this.rect.height / 2) + 'px'
          }
        },
        left () {
          switch (this.direction) {
            case 'top':
              return (this.rect.left + this.rect.width / 2) + 'px'
            case 'bottom':
              return (this.rect.left + this.rect.width / 2) + 'px'
            case 'left':
              return (this.rect.left - 12) + 'px'
            case 'right':
              return (this.rect.left + this.rect.width + 12) + 'px'
          }
        }
      },
      mounted () {
        this.initColor()
        this.hidden()
      },
      methods: {
        initColor () {
          switch (this.direction.toLowerCase()) {
            case 'left':
              this.arrowStyleObject = {
                borderLeftColor: this.background
              }
              break;
            case 'right':
              this.arrowStyleObject = {
                borderRightColor: this.background
              }
              break;
            case 'top':
              this.arrowStyleObject = {
                borderTopColor: this.background
              }
              break;
            case 'bottom':
              this.arrowStyleObject = {
                borderBottomColor: this.background
              }
              break;
          }

        },
        hidden () {
          let that = this
          window.setTimeout(function(){
            that.isShow = false
          }, this.time)
        }
      }
    }
  </script>

  <style type="text/css">
    .kiko-tool-tip {
      display: block;
      position: absolute;
      position: fixed;
      background-color: #3695CC;
      padding: 10px 10px;
      border-radius: 5px;
      color: #fff;
      white-space: nowrap;
      z-index: 99999999
    }
    .kiko-tool-tip.left {
      transform: translate(-100%, -50%);
    }
    .kiko-tool-tip.right {
      transform: translate(0, -50%);
    }
    .kiko-tool-tip.top {
      transform: translate(-50%, -100%);
    }
    .kiko-tool-tip.bottom {
      transform: translate(-50%, 100%);
    }
    .kiko-tool-tip.right .arrow {
      display: inline-block;
      position: absolute;
      content: '';
      width: 0;
      height: 0;
      top: 50%;
      left: -10px;
      border-top: 10px solid transparent;
      border-right: 15px solid #3695CC;
      border-bottom: 10px solid transparent;
      transform: translate(0, -50%);
    }
    .kiko-tool-tip.left .arrow {
      display: inline-block;
      position: absolute;
      content: '';
      width: 0;
      height: 0;
      top: 50%;
      right: -10px;
      border-top: 10px solid transparent;
      border-left: 15px solid #3695CC;
      border-bottom: 10px solid transparent;
      transform: translate(0, -50%);
    }
    .kiko-tool-tip.top .arrow {
      display: inline-block;
      position: absolute;
      content: '';
      width: 0;
      height: 0;
      left: 50%;
      bottom: -10px;
      border-top: 15px solid #3695CC;
      border-left: 10px solid transparent;
      border-right: 10px solid transparent;
      transform: translate(-50%, 0);
    }
    .kiko-tool-tip.bottom .arrow {
      display: inline-block;
      position: absolute;
      content: '';
      width: 0;
      height: 0;
      left: 50%;
      top: -10px;
      border-bottom: 15px solid #3695CC;
      border-left: 10px solid transparent;
      border-right: 10px solid transparent;
      transform: translate(-50%, 0);
    }
  </style>
  • index.js

  import Vue from 'vue'
  import ToolTip from './src/main.vue'

  ToolTip.installToolTip = function(event, opt) {

    var options = opt

    var rect = {};
    ['top', 'left'].forEach(function(property) {
      var scroll = property === 'top' ? 'scrollTop' : 'scrollLeft'
      rect[property] = event.target.getBoundingClientRect()[property] +
        document.body[scroll] +
        document.documentElement[scroll]
    });
    ['height', 'width'].forEach(function(property) {
      rect[property] = event.target.getBoundingClientRect()[property]
    });
    options.rect = rect
    var toolTip = Vue.extend(ToolTip)

    var component = new toolTip({
      data: options
    }).$mount()
    event.target.appendChild(component.$el)
  }

  export default ToolTip

adopt Element.getBoundingClientRect() Methods The size of the element and its position relative to the viewport were obtained, and then the prompt information was fixed.

confirm

confirm pops up a dialog box while retaining the page, which is suitable for larger scenarios. It can be used for displaying some complex information with checking bullet windows, or for displaying simple information only. Any title can be displayed by Title attribute, and the width of display area can be modified by width attribute.

  • confirm component structure

Same message component

  • main.vue

  <template>
    <transition name="bounce">
      <div class="kiko-confirm" v-if="visible">
        <div class="bg"></div>
        <div class="kiko-container" :style="{width: width}">
          <div class="header">
            {{title}}
            <i @click="close" class="icon-remove icon-large kiko-close-btn" v-if="closeVisible"></i>
          </div>
          <div class="content">
            <slot></slot>
          </div>
          <slot name="footer">
            <!-- <div class="kiko-footer" slot="footer">
              <a href="javscript:void(0)" class="kiko-btn make-sure">Determine</a>
              <a href="javscript:void(0)" class="kiko-btn cancel">cancel</a>
            </div> -->
          </slot>
        </div>
      </div>
    </transition>
  </template>

  <script type="text/javascript">
    import '../../../lib/icon/css/font-awesome.css'
    export default {
      name: 'kiko-confirm',
      props: {
        width: {
          type: String,
          default: '260px'
        },
        title: {
          type: String,
          default: 'information'
        },
        visible: {
          type: Boolean,
          default: false
        },
        closeVisible: {
          type: Boolean,
          default: true
        }
      },
      data () {
        return {
        }
      },
      methods: {
        close () {
          this.$emit('update:visible', false)
        }
      }
    }
  </script>
  • index.js

  import Vue from 'vue'
  import Confirm from './src/main.vue'

  export default Confirm

Here, we introduce it through component mode, which can be simple information prompt, or we can do some complex checking by ourselves. Display and hide components are referenced here sync modifier Or you can use the v-if instruction. Application slot To distribute content.

loading

Considering that full screen rendering may not be required, loading is only needed locally and can be passed on demand at specified locations. Custom directives To achieve, through Element.getBoundingClientRect() Methods According to the location of the elements and the size of the area, the method can automatically locate the image; if you want to render the whole screen, you need to add A. fullscreen modifier.

  • loading component structure
    Same message component

  • main.vue

  <template>
    <div class="kiko-loading" :style="{'top': top, 'left': left, 'width': width, 'height': height}">
      <div class="bg"></div>
      <div class="kiko-container">
        <i class="icon-spinner icon-spin icon-4x"></i>
      </div>
    </div>
  </template>

  <script type="text/javascript">
    export default {
      name: 'kiko-loading',
      data () {
        return {
          top: 0,
          left: 0,
          width: '100%',
          height: '100%'
        }
      }
    }
  </script>
  • index.js

  import Vue from 'vue'
  import Loading from './src/main.vue'

  const loadingConstructor = Vue.extend(Loading)

  Vue.directive('kiko-loading', {
    update: function(el, binding) {
      if (binding.oldValue != binding.value) {
        const options = {}
        options.fullScreen = binding.modifiers.fullscreen ? true : false;
        if (options.fullScreen) {
          options.top = 0
          options.left = 0
          options.width = '100%'
          options.height = '100%'
        } else {
          ['top', 'left'].forEach(function(property) {
            var scroll = property === 'top' ? 'scrollTop' : 'scrollLeft'
            options[property] = el.getBoundingClientRect()[property] +
              document.body[scroll] +
              document.documentElement[scroll] +
              'px'
          });
          ['height', 'width'].forEach(function(property) {
            options[property] = el.getBoundingClientRect()[property] + 'px'
          });
        }
        var component = new loadingConstructor({
          data: options
        }).$mount()
        var node = document.querySelector('.kiko-loading')
        if (node && node.parentNode) {
          node.parentNode.removeChild(node)
        }
        if (binding.value === true) {
          document.querySelector('body').appendChild(component.$el)
        } else {
          var node = document.querySelector('.kiko-loading')
          if (node && node.parentNode) {
            node.parentNode.removeChild(node)
          }
        }
      }
    }
  })

  export default Loading

npm outsourcing

  1. Make sure that the package.json file in your project's root directory is built

  2. Sign in npm official website register

  3. Log in npm login under your project directory (then fill in the information as prompted)

  4. Outsourcing npm publish

If there is an error in executing npm publish, it may be that your package name has been registered. Search the npm official website to see if it has been registered. If the package is successful, you can search for your own package on the npm official website.

Once the contract is successful, it can be passed.

`
import Vue from 'vue'
import Kiko from '../node_modules/kiko/index.js'
Vue.use(Kiko)
`
Introduce your plug-in 

Because of my limited knowledge, there are many areas that need to be improved. I hope you can give me more advice.

Keywords: Javascript Vue npm JSON

Added by hyeteck on Fri, 07 Jun 2019 00:40:56 +0300