Do VUE development, after the basic operation will be not special want to wanke a wanke vUE plug-in, let their own code can be used. Don’t worry, today and you together hand touch hand, oh bah, is hand, together with a pipe, oh bah, is a package based on vUE pay treasure password popover plug-in. It then explains how to write a Markdown description of the plug-in, publish it to Github, set up where the project will run on Github, and publish the NPM package.

A simple look at the renderings, the main implementation of password input to complete automatic trigger input callback function, custom title, custom highlight color, custom loading animation, password error pop-up, can clear the password and other basic operations.



Before developing vue plug-ins, what is the purpose of encapsulating plug-ins? The purpose of wrapping plug-ins is to make the code reusable, and since it is reusable, the encapsulation can be diversified as long as reusable operations are implemented. This is a little different from jq’s $.fn. MyPlugin = function(){}. Here’s what the official document says about the Vue plug-in:

Plug-ins typically add global functionality to Vue. There is no limit to the scope of plug-ins — there are generally the following:

  1. Add global methods or attributes such as vue-custom-element

  2. Add global resources: directives/filters/transitions, such as vue-touch

  3. Add some component options, such as vue-router, through the global mixin method

  4. Add Vue instance methods by adding them to vue.prototype.

  5. A library that provides its own API and one or more of the above mentioned functions, such as vue-Router

MyPlugin.install = function(Vue, options) {// The first method. Add global method or attribute vue.myGlobalMethod =function() {// logic... } // The second method. Add global resource vue.directive ('my-directive', {
        bind(el, binding, vnode, oldVnode) {// logic... }... }) // The third method. Inject component vue.mixin ({created:function() {// logic... }... }) // Fifth method. Add the instance method vue.prototype.$myMethod = function(methodOptions) {// Logic... } // The sixth way is to register the component Vue.component(component name, component)}Copy the code

These forms can be developed as our plug-ins. Isn’t the essence of plug-ins for code reuse? Use different formats depending on your packaging needs. For example, the Toast prompt can be vue. prototype, the input box automatically gets focus can be vue. directive, and custom components can be Vue.component.

Because our payment password box can be seen as a component, it comes in the form of Vue.com Pnent. Let’s start building a basic shell:

In order for you to see the project in action, first initialize a vUE project. Then create a new lib folder in SRC to store each plug-in, and create a new vpay folder under lib to store our plug-in.

Under the vpay folder, create a new index.js and a new lib folder, and our real plug-in is written in the new lib folder. The reason why this is done is because there are still packages to initialize NPM and publish to NPM:



Forget about the contents of the NPM package for a moment and leave that to you at the end. Look at the plugins first and create the corresponding file based on the above.

Then we start to build the basic shell of plug-in development, in the plugin index.js:

// pay.vue writes our component import vpay from'./pay'// Define our plugin const myPlugin = {// The plugin has a install method // the first argument to the method is the Vue passed in, Install (Vue, options) {// register it as a Vue component,'vpay'That's the component name, keyboard is the component that we developed Vue.component('vpay', vpay)}} // Finally export the plugin and use the plugin via vue.use () in main.jsexport default myPluginCopy the code

Once the plug-in is developed, it can be used in mian. Js like this:

// Import vpay from'./lib/vpay'// Use the plugin vue.use (vpay);Copy the code

The plugin can then be used directly in our pages in the same way as the component:

<! -- Payment password popover --> <vpay ref="pays"    
    v-model="show"               
    @close="close"    
    @forget="forget"    
    @input-end="inputEnd"
></vpay>Copy the code

Is it the same as the way we use plugins? With the basic idea and plug-in shell in place, it’s time to start developing pay.vue, the specific content of this plug-in. This part of the development, to put it simply, is like writing a parent and child component, because we want to end up using a custom component like the one above.

Pay. Vue file:

  • The first thing is the layout, so I’m not going to talk about it here, let’s just go to the code. The code is a little rough, and is mainly used for demonstration:

<template>    
    <div class="zfb-pay" v-if="show">        
        <div class="content"> <! -- Title bar --> <header class="pay-title">                
                <div class="ico-back" @click="cancel"></div> <h3>{{title}}</h3> </header> <! --> <div class="pass-box">                
                <ul class="pass-area">                    
                    <li class="pass-item"                        
                        :class="{on: password.length > index}"                        
                        v-for="(item, index) in digit"                         
                        :key="index"></li> </ul> </div> <! --> <div class="forget-pass">                
                <div class="forget-pass-btn" @click="forget"< div style = "box-sizing: border-box! Important; word-wrap: break-word! Important;" --> <ul class="keyboard">                
                <li @click="onKeyboard(1)">                    
                    <p class="num"><strong>1</strong></p>                    
                    <p class="character"></p>                
                </li>                
                <li @click="onKeyboard(2)">                    
                    <p class="num"><strong>2</strong></p>                    
                    <p class="character">ABC</p>                
                    </li>                
                <li @click="onKeyboard(3)">                    
                    <p class="num"><strong>3</strong></p>                    
                    <p class="character">DEF</p>                
                </li>                
                <li @click="onKeyboard(4)">                    
                    <p class="num"><strong>4</strong></p>                    
                    <p class="character">GHI</p>                
                </li>                
                <li @click="onKeyboard(5)">                    
                    <p class="num"><strong>5</strong></p>                    
                    <p class="character">JKL</p>                
                </li>                
                <li @click="onKeyboard(6)">                    
                    <p class="num"><strong>1</strong></p>                    
                    <p class="character">MNO</p>                
                </li>                
                <li @click="onKeyboard(7)">                    
                    <p class="num"><strong>7</strong></p>                    
                    <p class="character">PQRS</p>                
                </li>                
                <li @click="onKeyboard(8)">                    
                    <p class="num"><strong>8</strong></p>                    
                    <p class="character">TUV</p>                
                </li>                
                <li @click="onKeyboard(9)">                    
                    <p class="num"><strong>9</strong></p>                    
                    <p class="character">WXYZ</p>                
                </li>                
                <li class="none"></li>                
                <li class="zero" @click="onKeyboard(0)"><strong>0</strong></li>                
                <li class="delete" @click="deleteKey"></li> </ul> <! <div class="loading-wrap" v-if="payStatus ! = = 0">                
                <div class="loading"> <! <img SRC ="@/assets/loading.png" class="loading-ico" alt="" v-if="payStatus === 1">
                    <img src="@/assets/success.png" class="success-ico" alt="" v-if="payStatus === 2"> <! -- load text --> <p v-if="payStatus === 1">{{loadingText}}</p>                    
                    <p v-if="payStatus === 2">{{finishedText}}</p> </div> </div> <! <div class="pay-fail" v-if="isShowFail">                
                <div class="pay-fail-lay">                    
                    <h3 class="title">{{failTip}}</h3>                    
                    <div class="btns">                        
                        <div @click="reInput"Word-wrap: break-word! Important; "> <div @click="forget"> forgot password < / div > < / div > < / div > < / div > < / div > < / div > < / template >Copy the code

There is nothing to say about the layout. Roughly speaking, it is divided into what plates:

  • First, a full-screen mask layer, with the popover part bottom aligned.
  • Title bar: You can customize the popover title content
  • Password area: Digit customization, such as 4 – digit, 6 – digit, 8 – digit password forget. Cryptographic area black dot through pseudo class implementation.
  • Forget password jump: By triggering the forget event of the parent component, the parent component can perform specific jump operations or other operations.
  • Keyboard area: Only number keys can be deleted. Consider modifying some of the operations that add white space keys.
  • Loading prompt area: there are two states: loading and loading successfully. The password input completes the automatic trigger loading state and triggers the parent’s ind-end custom event, where the payment request can occur. Depending on the result of the request, inform the plug-in of the payment result. You can customize the loading and loading successful text, loading successful prompt stay time and so on. You can pass the loadingThis. $refs. Pays $success (true). Then (res = > {})Notifies the plug-in of the success result and fires when the success message stopsthenInside the operation.
  • Error password re-entry prompt: When the result of the request is an incorrect password, the request can be passed in the parent componentthis.$refs.pays.$fail(false)The plugin’s method is called to tell the plugin that the payment result is a password error, and the plugin will pop up an error message box. Since the above code was written and copied directly, variables and methods were inserted.

With the layout complete, let’s start with the implementation:

export default {
    data() {        
        return {            
            password: ' ', // Payment password payStatus: 0, // Payment status, 0 is stateless, 1 is paying, 2 is paying successfully failTip:'Payment password error', //             
            isShowFail: false}}},Copy the code

1. Define a password variable in data to store the input payment password. Each numeric key in the keyboard area corresponds to a key value (0-9). When you click the numeric key, get the corresponding key value and assign it to update the value of password, corresponding to the methods below
onKeyboard
Methods:


This.password = (this.password + key).slice(0, 6); this.password = (this.password + key).slice(0, 6); },Copy the code

$emit(‘ inputend ‘) notify-emit (‘ inputend ‘) = $emit(‘ inputend ‘) = $emit(‘ inputend ‘) = $emit(‘ inputend ‘)

Watch: {// listen for the payment password, and trigger the ind-end callback after the payment password is entered // Inform the parent component of the input password as an argument, that is, the ind-end function parameter can get the password password (n, o) {if (n.length === this.digit) {                
            this.payStatus = 1;                
            this.$emit('input-end', this.password)                            
        }            
    }    
},Copy the code

This. digit is the value passed through prop to set the number of digits in the payment password box. The default is six:

// props: {// Digits of the payment password box: digit: {type: Number,            
        default: 6        
    },
}Copy the code

2. Complete the password input, start to do the password back deletion, namely each back deletion, delete the last digit of the password, a bit similar to the algorithm in the heap (last in first out), a bit far away, here do not use:

// Delete the password backdeleteKey(){// If the password is empty, do not delete the passwordif (this.password.length === 0) return; This.password = this.password.slice(0, this.password.length-1); },Copy the code

If the password length is 0, the system does not delete the password overwrite. If the password length is not 0, the system intercepts the new password from 0 to 1, that is, the last digit of the password is deleted.

3. When the password entered reaches a specified length, the custom event of the parent component is automatically triggered. This is written in the parent component, which will be introduced in the demonstration of invoking the plug-in later. Then there will also be the corresponding operation to cancel the payment popover, that is, click the back button in the upper left corner of the popover to cancel the payment and close the popover:

// Cancel the paymentcancel() {// Cancellations are not allowed during paymentif (this.payStatus === 1) return; // Clear the password this.password =' '; This.paystatus = 0; this.paystatus = 0; // Close the component and trigger this synchronization between the parent and child components.$emit('change'.false); // Trigger the parent component's close custom event this.$emit('close');        
},Copy the code

When cancellations are made, the current state of the payment must be determined. If the payment is in the current state, the cancellation is not allowed. The primary payStatus has three values: 0 stateless, 1 paid, and 2 paid successfully. The next step is to clear the password, initialize the state of the payment, close the popover, and tell the parent that the parent can have a custom event write callback for close.

$emit(‘change’, false); $emit(‘change’, false); $emit(‘change’, false);



When we use the plug-in, we want to use the value of v-Model to control the display and hide of components, just like many libraries use V-Model. So here’s how this can be done with the V-Model:

Or the component’s prop property, using the prop show property to control the display and hide of the component:

// Hide the component show: {type: Boolean,            
    required: true,            
    default: false        
},Copy the code

Then in the hook of the Model:

model: {        
    prop: 'show',        
    event: 'change'    
},Copy the code



Finally, this field is used to control display and hide in HTML. V – Model content here not to do the introduction, back here to update a link address, in another article in detail.

4. When your password is entered, the parent component’s input-end callback is automatically triggered. When you initiate a payment request in the input-end callback, the background will return the payment status to you, such as payment success or password error. Unset payment can be judged or prompted before the payment popover is hoisted. When you get the payment result, notify the plugin by calling the plugin’s $success or $fail method. Let’s see how this works, and then how to implement the $success and $fail methods in the plugin:



When we invoke the pay-keyboard, we define ref=”key”, so we can point to the current plug-in instance with this.$refs.pay. The usage is simple and the comments are clear. I won’t explain it. Here’s the plugin’s $success method:

// The payment was successful$success () {            
    returnNew Promise((resolve, reject) => {// Make a new Promise(reject, reject) => {// make a new Promise(reject, reject) => {// make a new Promise(reject, reject) => {// make a new Promise. // Hide the entire payment popover after the specified interval and resolvesetTimeout(() => { this.cancel(); resolve(); }, this.duration); })},Copy the code

This method returns a Promise object, and the promise is immediately executed. The promise is returned in order to write the callback on the call through the THEN method, which is more elegant. Within the PROMISE, a change in the payment status is made, and then the pop-up is closed and resolved after the time set for the payment success status to be displayed. So the action in the this.$refs.pay.$success().then() method will be executed after waiting for the success message to finish, which means the popover is hidden.

// Payment failure // Hide the loading prompt box and display the payment failure confirmation box$fail (tip) {            
    tip && typeof tip === 'string'&& (this.failTip = tip); This.paystatus = 0; this.paystatus = 0; // Display a password error popup this.isShowFail =true;        
},Copy the code

The $fail method is for the plugin to display a pop-up with an incorrect password when it knows that the payment result is an incorrect password. The password error pop-up is customizable. Get a custom error message using the tip parameter.

The error prompts a pop-up window with two buttons, one for re-enter and one for forget password.

Click Re-enter, which is sure to hide the popover, and then the situation has been entered with the password. From there, write a reInput method in methods to implement this function:

// Re-enter // clear the password previously entered, hide the payment failure prompt boxreInput () {            
    this.password = ' ';            
    this.isShowFail = false;        
},Copy the code

Then you can re-enter the payment password.

Forget the password, here we can give control of the click action to the parent component. So, let’s write a clickable method for forgetting your password, where the forgotten password can be used as the same operation as the forgotten password in the password area above. Of course, you can also develop separate operations according to your own needs. Here it is as the same operation:

// Forgetting the password triggers the forget-only custom event of the parent componentforget () {            
    this.$emit('forget');        
}Copy the code

From there, you can do things like a connected jump in the @Forget custom event of the parent component.

Of course, our prop receives the following parameters:

// Popover title: {type: String,            
    default: 'Please enter your payment password'}, // loadingText: {type: String,            
    default: 'Paying in progress'}, // Pay successful text prompt finishedText: {type: String,            
    default: 'Successful payment'}, // Display time for payment success message duration: {type: Number,            
    default: 500        
}Copy the code

With these prop parameters, we can configure them when initializing the plug-in.


After the development of the plug-in is complete, it is called. We first introduce our plug-in in main.js and initialize the plug-in:

// Import the plugin, the location is your plugin location import payPassword from'./lib/zfc-password'// Initialize the plugin vue.use (payPassword)Copy the code

Then use it within our page like this:

<vpay          
    v-model="show"                       
    ref="pays"            
    @close="close"            
    @forget="forget"            
    @input-end="inputEnd"      
></vpay>
Copy the code

At this point our plug-in development is basically complete. It has been submitted to Github and sent to the github project address and demo address. Please check it by yourself.



After the plug-in is written, we need to simply write a plug-in usage document. For example, the component libraries we see on Github come with instructions, including apis, event descriptions, etc. Picture and truth, above:

Is not very familiar! Yes, this is the documentation in MarkDown format. There are a lot of things to say about MarkDown, but let’s just talk about some common syntax for writing markDown documents, which should be enough for you to write your own documents.

Markdown is a lightweight markup language created by John Gruber. It allows people to “write a document in a plain text format that is easy to read and write, and then convert it into a valid XHTML(or HTML) document.” This language incorporates many of the features of plain text markup already found in E-mail.

Markdown has been in use for a long time, and a lot of writing is using MarkDown documents, including our gold writing can also switch markdown safely. Here’s the common syntax for markdown. In the root directory we created for vue, you will find a file called reame.md, which will be used to write the project documentation. If the project is uploaded to Github, this document will correspond to the usage documentation shown above.

There are other ways to write markdown documents for each format, but here is only one of the common or preferred formats:

  • The writing form of the title corresponds to H1, H2, H3, H4, H5,h6

# Level 1 title
## Secondary title
### Level 3 title
#### Level 4 Title
##### Five-level title
######Copy the code

Effect:



  • Unordered lists and ordered lists:

* 1111 * 2222 * 3333 1. 1111 2. 2222 3Copy the code

Effect:



  • Form writing:

Cambodian | | event parameters of | | | - | : - | : - | : - : | | | input - end password input after the completion of the callback function | - | | close | password following the closure of the popup window callback function | - | | forget | | - | click forgot password callback functionCopy the code



Form here by the way, the first line of the title of the corresponding form, the second table header from form to content, and here you can define table alignment, namely | – | the default left alignment, | : – | on the left to add, said the column left alignment, the right add: this column right alignment, both sides add: center alignment.

  • Introduce a code block:

```javascript
this.$refs.pays.$success(true).then(res => {    
    console.log('Successful payment')     
    this.$router.push('/success')}) ` ` `Copy the code

That is, you can add a code block between the two. It’s the one under the ESC key, not the single quote.

  • Image introduction:

! [Payment password box demo GIF](./static/pay.gif)Copy the code

Through! [Image description](image path) can be imported images. The effect is shown in the GIF above.

  • Introducing hyperlinks:

/ demo presentation page (https://chinaberg.github.io/vpay/dist/#/, 'Payment password popover demo page ')Copy the code

[] sets the name of the link. The first parameter in () is the link address and the second parameter is the value of the link title attribute. The second parameter is optional. The effect is as follows:



The writing syntax for MarkDown documents covers some of the most commonly used. For more information on markDown syntax, see the documentation.


Upload the plugin to Github and set the project’s demo preview url.

The plugin is developed, the documentation is written, and the following is to upload the github, set up the Github project presentation page, and share it with more people.

  • First of all, a Github account is a must.
  • Create a New project on Github: click the plus sign in the upper right corner, select New Repository to create a New project, enter project name -> Project Description -> Create Project






  • If you are not familiar with git, go to the git website and learn some basic git operations before you start. Liao Xuefeng’s Git tutorial on the Internet is more suitable for beginners, and it is relatively easy to learn at the beginning.



  • Open the terminal in your project or on the CMD command line, as SHOWN here in the VSCode editor terminal:



  • Because our VUE project needs to be packaged before it can run. So we need to NPM run build to package the project. After packaging, you can open the root directory dist folder, which has an index.html file, open the run, if it is white screen (it must be white screen), it is wrong path, here you need to change the package path, the details will not be detailed, in another article, there is a solution to the wrong path after packaging resources. Here’s the link, very simple, just add a configuration.
  • After packaging, we initialize our project through Git, the most basic steps are:
  1. git initInitialize the Git project
  2. git checkout -b masterCreate a new master branch
  3. Because vue-cli default configuration, setgitIgnore monitoring the dist folder that we’re packaging, so I’m going to cancel ignore here and letgitmonitoringdistFolder, otherwise the remote library will not be committeddistFolders: Open the.gitignore file in the root directory. This is the git configuration file where you can set the types of files that Git does not need to monitor. So let’s put it here/dist/I’m going to delete this line of code, just so we can go back togit add .Will be monitoreddistFolder.At this point, if you run the git status command, you can see that Git is already monitoring the DIS folder
  4. git add . Notice that there is a dot here, and that dot and add directly have Spaces.

  5. Git commit -m" Initialize alipay Password popup"Git Local Commit
  6. After local commit, we need to connect to the Github remote repository:git remote add origin [email protected]:chinaBerg/my-project.gitThe following address is the SSH address of your remote library, do not copy my address here, you will not be successful in connecting to my remote library. Then rungit remote -vCheck whether the connection is successful:You can see that my remote library has been successfully connected. Let’s start with pushing local code to remote libraries.
  7. For the first commit, since the local branch is not associated with the remote branch, we need to associate the remote library for the first push:git push -u origin master, including-u origin masterLink the current branch to the remote master branch, so that the contents of the current local branch will be committed to the remote master branch when you commit.

    You can see that the commit is successful. Next, we open the project on Github and have a look. After refreshing, we can see that the project has been transferred to remote, including our source code, the packaged dist file, and the readme.md documentation we wrote earlier:


After the file is uploaded, how do we set it up to see the project running on Github?

In the current project, click the Setttings option, select the Options TAB, pull down the position at the bottom to find the GitHub Pages area, click the drop-down menu to select the Master Branch option, and click the Save button to save.



And then we’ll see that there’s a URL for this location. Yes, this is our project path, but the only project we can allow after packaging is in the dist folder, so if we want to access the packaged project, we just need to concatenate after this path, for example:https://chinaberg.github.io/my-project/Dist /index.html You now access me this project may not exist because I have deleted it.

At this point, we are done uploading github.

In fact, the main knowledge here is the use of Git. Using Git to version control our code and connect to remote libraries is a basic skill that we as developers must know. If you don’t know Git yet, you should take the time to learn. Otherwise here estimate will pit want to give up!


Release the NPM package for later download and use.

We have already uploaded the plugin code to Github, so can we also make an NPM package and publish it to NPM? The answer is yes, so once we need to use the plug-in, we can directly install the implementation of NPM I vpay and so on into our project, isn’t it convenient?

As mentioned in the file directory at the beginning of this article, we wrote the plug-ins in the second lib. The entire Vpay folder is what we’re going to publish as an NPM package. Readme.md is the documentation, just like the one on Github, you can simply copy the one in the root directory first.

Then there is the index.js below the vpay file, which will export our plugin according to the code:

module.exports = require('./lib')Copy the code

In this file, we export our plug-in, since we are actually importing this index.js when we use it.

The most important thing to mention is the package.json file, which was not originally available. This is the configuration file for the NPM package. To initialize an NPM package configuration file, go to the vpay folder and run the NPM init command on the terminal. At this point, it will ask you a series of questions to complete the configuration file:

  • Name: package name. Default is folder name. But the name needs to be unique. If your name has already been used, you have to change it. To see if the package name exists, you can go to the NPMJS website and search for your package name. If you can’t find it, you can use it.


  • Version: The version of the package. The default is 1.0.0. You can change it, such as 0.1.0 or 2.0.1.
  • Description: Indicates the package description. Describe what your bag is for.
  • Entry point: Package entry file. Default isIndex.js, which can be customized.
  • Test command, so just hit enter, because we don’t need this yet.
  • Git repository: the address of a git repository that NPM automatically reads.gitThe directory is the default value for this entry. If not, press Enter to skip it.
  • Keyword: the keyword of the package. This will affect how the user can search for your package, which can be interpreted as search engine keywords. Suggest keywords that accurately describe your package, such as “vpay vue-pay vue-password password”.
  • You’re the author. For example, your NPM or Github account
  • License: open source protocol. Press Enter.

  • At this point, we’ve actually developed the native package, and we need to test whether the package works. How do you test it? We know that when we install the plug-in using NPM, we actually install the plug-in in the root directory node_modules file. So, now that we’ve developed the native package, we’ll copy the vpay folder directly into the node_modules folder. Then use the plugin in main.js as usual:

    // Import vpay directly, no need to write path import vpay from'vpay'
    
    Vue.use(vpay);Copy the code

    The test shows that everything is normal, which means our bags are ok.

    Now it’s time to publish. Before Posting, we need to have an NPM account first. If you don’t have an account, go aheadNPMJS official website registrationAn account, here a hint, when registering a user name often may not pass, so it is more convenient to add some numbers at the beginning of the letter. Full name is a nickname, email address, and the following two are user name and password. Sometimes usernames will always prompt you for irregularities, so it’s faster to add letters and numbers.

    Back to the topic, first switch to our vpay file directory, and then run the NPM login command to login to our NPM account, he will prompt you to enter the user name and password of NPM, note that there will be no prompt when you enter the password, do not think there is no response here. You just type, but you can’t see anything, and when you’re done, press enter, and type in NPM’s email address. Finally, enter, here is a point to note, if you are installed before Taobao image, it will not succeed, because you want to publish the NPM package to NPM image, not taobao image. We can usually through Taobao mirror to speed up the download speed, because Taobao mirror is actually every ten minutes to NPM on the latest resources synchronized to their own body. So you log in and publish through NPM’s image.

    If taobao image is configured, first set back to NPM image:

    npm config set registry http://registry.npmjs.org Copy the code

    Then run the NPM login command on the terminal:



    The last line Logged in as… The login is successful.

    After the login, run the NPM publish command to publish the NPM package to the NPM.



    And that’s a successful release. Let’s go to the NPM website and check our bags:



    If you don’t find it after Posting, wait a few minutes.

    Click on it and check it out. Everything is fine. In the future, we can directly bump the plug-in into our project through NPM I vpay.

    At this point, we’ve basically completed the development, documentation, github release, and NPM package, and everything is ready to work. The style of the plug-in is a little rough in some places, but the main purpose of this article is to demonstrate the plug-in development process. I hope I can help those in need.


    If you feel like it, you can collect it or start it ~~❤

    GitHub, check out demo, NPM