Not willing to be a wheeler!!!
Recording the Hard Way of a Picture Preview Component for an Internship Rookie~
Instruction mode and service mode are used in many components of elementUI, such as: loding, message, etc.
Take the loading component as an example:
Instruction mode:
<template> <div :v-loading.fullscreen="true">Full screen coverage</div> </template>
Service model:
const loading = this.$loading({ lock: true, text: 'Loading', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' });
Like most Mengxin, what is service?
- First look at the directory structure of elmentUI:
Open the node_modules directory and find the elementUI directory below:
The element-ui_ src_ index. JS file has a large registration information for the components, focusing on finding the loading we are looking for.
// ... // directive instruction loading Vue.use(Loading.directive) // prototype service loading Vue.prototype.$loading = Loading.service // ...
The instruction Vue.use() is used by Vue to install plug-ins. If the parameter passed in is an object, the object provides an install method. If it is a function, the function is regarded as an install method. When the install method is called, the Vue is passed in as a parameter.
Start!
Let's first look at what the ghost is in the load / index. JS file?
//Instruction file and service file are introduced, directive is instruction mode file, index.js is service mode file. import directive from './src/directive'; import service from './src/index'; export default { //The install method registers components, not to repeat the use of install, as described in the star-pic-list Picture Preview Component article install(Vue) { Vue.use(directive); //Register a $loading object on the prototype object of vue. This $loading is very familiar. Look at the use of the above service mode, use this.$loading, and find the source. Vue.prototype.$loading = service; }, //Introduced directive file directive, //Introduced index.js file service };
v-loading instruction parsing
It's too long, and we only use fullscreen modifiers.
// Introduce. vue file import Vue from 'vue' // Introduce load. Vue basic file, which contains component infrastructure, such as html structure, page structure of loading display. import Loading from './loading.vue' // The extended () constructor will be highlighted later. // Vue.extend() is a Vue constructor, which returns an extended instance constructor, that is, a Vue instance constructor with some preset options. // Mask literally means mask, masking, you can guess that this return constructor through Vue.extend(Loading) should be used for the masking layer when we load. // loading is the default option, just like in the vue example, there are components, name, data, methods... it seems a little clear. const Mask = Vue.extend(Loading) const loadingDirective = {} // Remember how to use Vue.use()? If the object is passed in, the object needs an install attribute loadingDirective.install = Vue => { // The toggle Loading method looks at the name by toggling the display and hiding of loading.~ const toggleLoading = (el, binding) => { // If the binding value is true, insert the loading element // Binding value is an object, including instruction name, instruction binding value, modifiers modifier object, etc. Specifically, you can understand the content of custom instructions. if (binding.value) { //binding.value is the bound instruction value if (binding.modifiers.fullscreen) { Do you remember the instructions we inserted? : v-loading.fullscreen="true" , .fullscreen It's the modifier. insertDom(document.body, el, binding) //insertDom knows by name that it is inserting new elements } // visible is the value defined in load. Vue data } else { el.instance.visible = false } } const insertDom = (parent, el, binding) => { // loading is set to visible el.instance.visible = true // If appendChild adds the same element, it will not be repeated parent.appendChild(el.mask) } // Register directive instructions here Vue.directive('loading', { bind: function(el, binding, vnode) { // Create a subcomponent, similar to new Vue(options) // Returns a component instance const mask = new Mask({ el: document.createElement('div'), // Some people will be confused when they see this. Why does this data not follow the official Vue recommendation to pass in a function? // In fact, there are both. // A little bit of extension. In the Vue source code, data is delayed. // Stick a little Vue source code up // return function mergedInstanceDataFn() { // let instanceData = typeof childVal === 'function' // ? childVal.call(vm, vm) // : childVal; // let defaultData = typeof parentVal === 'function' // ? parentVal.call(vm, vm) // : parentVal; // if (instanceData) { // return mergeData(instanceData, defaultData) // } else { // return defaultData // } // } // Instance Data is the data we are passing in now: {} // defaultData is the data() {} in our load. Vue // After reading this code, it should be easy to understand why objects can be passed in. data: { fullscreen: !!binding.modifiers.fullscreen } }) // Mount the created subclass on el // Recommendations in directive documentation // It should be guaranteed that all parameters (binding, vnode) except el are read-only. el.instance = mask // Mount dom // Bid calls only once, assigning el.mask to bind, so el.mask refers to the same dom element. el.mask = mask.$el // Run toogle Loading if the binding value is true binding.value && toggleLoading(el, binding) }, update: function(el, binding) { // If the old is not worth the new (usually when true is switched to false) if (binding.oldValue !== binding.value) { // Switch Display or Disappearance toggleLoading(el, binding) } }, unbind: function(el, binding) { // Execute component destruction when component unbind el.instance && el.instance.$destroy() } }) } export default loadingDirective
For more information on extend (), please refer to Here Very familiar and easy to understand!
Principle of loading Service Mode Call
Look directly at the source code:
import Vue from 'vue' import loadingVue from './loading.vue' // Like instruction mode, create instance constructors const LoadingConstructor = Vue.extend(loadingVue) // Define variables. If full-screen loading is used, ensure that there is only one global loading let fullscreenLoading // Here you can see something different from instruction mode. // After close is invoked, the element is removed and the component is destroyed LoadingConstructor.prototype.close = function() { setTimeout(() => { if (this.$el && this.$el.parentNode) { this.$el.parentNode.removeChild(this.$el) } this.$destroy() }, 3000) } const Loading = (options = {}) => { // If fullscreen is passed in when loading is called and fullscreenLoading is not falsy // Fulscreen Loading only assigns values below and points to the loading instance if (options.fullscreen && fullscreenLoading) { return fullscreenLoading } // There's no need to talk about it here. It's the same as in the instructions. let instance = new LoadingConstructor({ el: document.createElement('div'), data: options }) let parent = document.body // Direct addition of elements parent.appendChild(instance.$el) // Set it as visible // In addition, when I wrote here, I consulted the relevant information. // I've always understood that nextTick is a callback after the dom element has been updated // But that may not be the case. I will continue to study it later. // If there's enough dry goods, I'll write an article about next Tick ui-render microtask macrotask Vue.nextTick(() => { instance.visible = true }) // If the fullscreen parameter is passed in, the instance is stored if (options.fullscreen) { fullscreenLoading = instance } // Return an instance to call the close() method on the prototype for convenience return instance } export default Loading
Now Learn to Use - Write a Click-on Picture Preview Component for a Trial
Directory structure:
directive.js is the instruction mode file, index.js is the service mode file, star-pic-preview.vue is the basic single file, including the basic html structure.
Look at the instruction mode first:
- Use:
I used the instructions directly without passing parameters, because the function is simple and the default parameter is false.
<img src="http://img5.imgtn.bdimg.com/it/u=3300305952,1328708913&fm=26&gp=0.jpg" v-pic-preview >
- Effect:
Click to appear the mask layer and center the picture to display the preview.
Service model:
- Use:
<img src="http://img4q.duitang.com/uploads/item/201502/22/20150222191447_jdBYa.thumb.700_0.jpeg" @click="openImagePreview2" >
methods: { // service mode openImagePreview2(e) { // If you only send pictures this.$picPreview(e.target.src); //If you pass complex objects, you can configure the background color of the mask layer, etc. // this.$picPreview({ // background: 'rgba(0, 0, 0, 0.7)', // imageUrl: e.target.src, // }); }, }
- The effect is as good as above.