Historical review:

  • 【 VUE series 】 Gracefully generate dynamic forms with VUE (I)
  • 【 VUE series 】 Gracefully generate dynamic forms with VUE (2)
  • Vue series: Vue-DevTools you don’t know
  • Vue series vUE – Router source code analysis
  • [VUE series] In-depth understanding of VUex
  • 【 VUE series 】 VUE and EChats combine spring, vUE plug-in Vechart
  • Vue series ESLint is configured for the vue2. X project
  • [VUE series] Vue2. X project configures Mocha unit test
  • [VUE series] Two pictures, figure out the diff algorithm, really sweet ah!
  • [VUE series] Lazy loading of vue-Router routes occurs when element-UI is introduced on demand
  • Vue series the correct way to encapsulate common popover components
  • [VUE series] Develop components, package into VUE plug-ins, write documents, configure GH-Pages branch demo, release NPM package one stream

How did you decide whether to build a wheel? As far as I am concerned, it is worthwhile to build wheels by packaging repetitive codes that need multiple calls into components and plug-ins and developing the tedious operation process into an efficiency improvement tool, which can simplify workload and improve work efficiency later. Seal components for business, seal plug-ins, to improve the efficiency of tools, do valuable things, to achieve self-value.

Let’s take a look at what wheel we made this time. According to our demand for leave approval, when we ask for leave, the date picker is carried in the afternoon, which is not common in mobile terminals. It is usually in the form of calendar, and our products require the form of picker scroller. I’ve been looking for nothing.

Well, this is the effect, there is no way, but to build their own hand. This is how I built the wheel. Develop a half-day date picker component from the beginning to meet the needs of use; It is used in many places in business and packaged as VUE plug-in; The package was found to be too large after encapsulation, and the plug-in was optimized. After the completion of a delicate VUE plug-in package, write the use of the plug-in document, convenient for everyone to use; Then upload to Github and configure GH-Pages to display online demo. Finally published to NPM, a three-way plug-in is complete. ✌ ️ ✌ ️ ✌ ️

Let’s take a look at the enclosed date picker, how to use? 👇

vue-halfday-datepicker

A simple vUe-based belt, afternoon date picker

Demo

Online address: https://habc0807.github.io/vue-halfday-datepicker/index.html

The characteristics of

  • The mobile terminal
  • Bring, afternoon
  • Date picker
  • Vue plug-in

The installation

npm i vue-halfday-datepicker -D
cnpm i vue-halfday-datepicker -D
yarn add vue-halfday-datepicker -D
Copy the code

Import and register

Import and register in the entry file of a single page application

import VueHalfdayDatepicker from 'vue-halfday-datepicker'
Vue.use(VueHalfdayDatepicker)
Copy the code

use

<template> <div id="app"> <h2> A VUE based date picker Demo</h2> <div class="pickerSelect" @click="onOpenPicker">{{pickerValue }}</div> <vue-halfday-datepicker :show="isShow" @onConfirm="onConfirmHandle" @onCancel="onCancelHandle"/> </div> </template> <script> export default { name: 'app', data () { return { isShow: false, pickerValue: 'Test: select'}}, methods: { onOpenPicker(e) { this.isShow = true }, onConfirmHandle(v) { this.value = v this.pickerValue = v this.isShow = false }, onCancelHandle(e) { this.isShow = false } }, } </script> <style> </style>Copy the code

Github: vue-halfday-datepicker: vue-halfday-datepicker

How to develop a belt, afternoon date picker component

Finding a solution

At the beginning, I wanted to save trouble and found a third party to use it directly. I searched github for a long time, then searched vue UI component library, and found that VUX dateTime actually had this component. Kaisen, try it quickly, start to introduce this component as needed, through the manual configuration of the VUX official website, configuration is really cumbersome, the focus of the configuration can not be used. Of course, I will not easily give up, from beginning to end in accordance with the configuration again, still not good.

Secondary wrap picker

I had to give up VUX for a while. Another shortcut, the date picker, is not also a picker, why not based on picker on the basis of the secondary encapsulation?

So I went to Mint UI and used its picker to do a secondary wrapper. I have to admit that the Mint UI’s quick start documentation is great and easy to configure. Because only one component is needed, importing on demand requires the help of the babel-plugin-Component to reduce the size of the project. NPM install babel-plugin-component-d and change.babelrc to:

{
  "presets": [["es2015", { "modules": false}]],"plugins": [["component"[{"libraryName": "mint-ui"."style": true}}]]]Copy the code

How is the date picker developed

Of course, the most important is the data processing of the Picker slots four-column array, and the data update for picker changes. Let’s look at slots first:

slots: [
    {
        flex: 1.values: yearsArr,
        className: 'slot1'.textAlign: 'center'.defaultIndex: defalutYear,
    }, 
    {
        flex: 1.values: monthsArr,
        className: 'slot2'.textAlign: 'center'.defaultIndex: defalutMonth
    },
    {
        flex: 1.values: daysArr,
        className: 'slot3'.textAlign: 'center'.defaultIndex: defalutDay
    },
    {
        flex: 1.values: noonArr,
        className: 'slot4'.textAlign: 'center'.defaultIndex: 0,}]Copy the code

We need an array of four columns: an array of years, an array of months for the current year, an array of days for the current month, and an array of afternoons. The month array is usually from 1 to 12 months, and the afternoon array is also very simple. By default, we specify 10 years before and after the year array. The special calculation is the day array. In fact, the calculation rules are roughly based on whether it is February or not. If it is leap year or not, November is 30 days, and other months are 31 days. Well, for sauce, look at the code 👇.

/** * is a leap year * @param {*} year */
function isLeapYear (year) {
  return year % 100! = =0 && year % 4= = =0 || year % 400= = =0
}

/** * Count the number of days in each month * @param {*} year * @param {*} month */
function getMaxDay (year, month) {
  year = parseFloat(year)
  month = parseFloat(month)
  if (month === 2) {
    return isLeapYear(year) ? 29 : 28
  }

  return [4.6.9.11].indexOf(month) >= 0 ? 30 : 31
}
Copy the code

Each time the picker updates, it recalculates the value of the data in the array, updating the selected date in time. Component development is complete, there are actually a lot of details need to pay attention to, such as default display, updated display, etc., I just said that the main process.

How to package a Vue plug-in

With the component development completed, I had the idea to seal the plugin. First, the component needs to reference the mint-UI triad, introducing picker on demand, and second, configure on-demand loading by adding the.babelrc file in the project root. This series of operations, if the subsequent needs or other partners also want to use it, will feel more troublesome. For our multi-page application, we need to do the same process again. It would be better to package a vUE plug-in, which is much easier to use.

From the perspective of business value, it is worth building a rocket. If the above process can be encapsulated as a VUE plug-in, it is only necessary to introduce and use it later. The configuration process, loading on demand and all that goes into the Vue plugin, building the wheels for the business, that’s what I’m going to do.

Project initialization

I saw webpack-Simple recommended by someone while I was packing the vue plugin, so I gave it a try and it worked fine. Create a folder named vue- plug-in by using vue init webpack-simple vue- plug-in name. The directory tree of the project is as follows.

. ├ ─ ─ the README. Md ├ ─ ─ dist ├ ─ ─ index. The HTML ├ ─ ─ package. The json ├ ─ ─ the SRC │ ├ ─ ─ App. Vue │ ├ ─ ─ assets │ │ └ ─ ─ logo. The PNG │ ├ ─ ─ lib │ │ ├─ ├─ ├─ ├.js │ ├─ ├.js │ ├─ ├.js │ ├─ ├.jsCopy the code

SRC is the source code and lib is the plugin part.

Modifying configuration Items

Modify the package. The json

Name, main, Author and repository are changed as follows:

  • Name Specifies the plug-in name
  • The last build file path of the main plug-in
  • Author Basic information about an author
  • Repository Basic information about a repository
{
  "name": "vue-halfday-datepicker"."description": "A date picker"."main": "dist/vue-halfday-datepicker.js"."version": "1.0.1"."author": "habc0807 <[email protected]>"."license": "MIT"."private": false."scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot"."build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },
  "repository": {
    "type": "git"."url": "git+https://github.com/habc0807/vue-halfday-datepicker.git"
  },
  "browserslist": [
    "1%" >."last 2 versions"."not ie <= 8"]."devDependencies": {
    "babel-core": "^ 6.26.0"."babel-loader": "^ 7.1.2." "."babel-plugin-component": "^ 1.1.1"."babel-preset-env": "^ 1.6.0." "."babel-preset-stage-3": "^ 6.24.1"."cross-env": "^ 5.0.5." "."css-loader": "^ 0.28.7"."file-loader": "^ 1.1.4." "."mint-ui": "^ 2.2.13." "."vue": "^ 2.5.11"."vue-loader": "^ 13.0.5"."vue-template-compiler": "^ 2.4.4." "."webpack": "^ 3.6.0"."webpack-bundle-analyzer": "^ 3.8.0." "."webpack-bundle-tracker": 1 "" ^ 1.0.0 - alpha.."webpack-dev-server": "^ 2.9.1." "
  },
  "bugs": {
    "url": "https://github.com/habc0807/vue-halfday-datepicker/issues"
  },
  "homepage": "https://github.com/habc0807/vvue-halfday-datepicker#readme"
}
Copy the code

Modify the webpack. Config. Js

Here we reserve the entrance of the page and the entrance of the plug-in, which are used in the form of components first. When there is no problem, we package the components into plug-ins, and then check the presentation effect in the page, or fix the small bugs in the plug-in.

entry: './src/main.js', // page entry // entry:'./src/lib/index.js'Output: {path: path.resolve(__dirname,'./dist'),
    publicPath: '/dist/',
    filename: 'build.js', // page generation file // filename:'vue-halfday-datepicker.js'// Plugin generation file libraryTarget:'umd',
    umdNamedDefine: true
},
Copy the code

In the process of optimizing the plug-in, some additional configurations are added, and the final webpack.config.js is shown in the plug-in optimization section.

Encapsulation plug-in

The vueHalfdayDatepicker. vue plugin is a package that uses mint-UI’s MT-picker. The main thing I’m going to do is picker’s four-column array slots, which was introduced in the first module but won’t be covered here.

<template>
    <div v-show="show" class="half-day-date-picker">
        <div class="bg"></div>
        <div class="select-date-container">
            <section class="picker-wrap">
                <div class="picker-toolbar">
                    <div class="btn cancel" @click="onCancel"> cancel </div> <div class="btn confirm" @click="onConfirm"</div> </div> <mt-picker :valueKey="" '"
                    :defaultIndex=10
                    :visibleItemCount=9
                    :slots="slots" 
                    @change="onValuesChange"
                ></mt-picker>
            </section>
        </div>
    </div>
</template>

<script>
import { Picker } from 'mint-ui'
import 'mint-ui/lib/style.css'

import {
    yearsArr,
    monthsArr,
    daysArr,
    noonArr,
    defalutYear,
    defalutMonth,
    defalutDay
} from '.. /tools/makeData.js'

export default {
    name: 'vue-halfday-datepicker',
    props: {
        show: {
            type: Boolean,
            required: true,
            default: () => null,
        }
    },
    components: {
        [Picker.name]: Picker,
    },
    data: function() {
        return {
            pickerValue: ' ',
            slots: [
                {
                    flex: 1,
                    values: yearsArr,
                    className: 'slot1',
                    textAlign: 'center',
                    defaultIndex: defalutYear,
                }, 
                {
                    flex: 1,
                    values: monthsArr,
                    className: 'slot2',
                    textAlign: 'center',
                    defaultIndex: defalutMonth
                },
                {
                    flex: 1,
                    values: daysArr,
                    className: 'slot3',
                    textAlign: 'center',
                    defaultIndex: defalutDay
                },
                {
                    flex: 1,
                    values: noonArr,
                    className: 'slot4',
                    textAlign: 'center',
                    defaultIndex: 0,
                }
            ],
        }
    },
    methods: {
        onOpenPicker(e) {
            this.$emit('onOpenPicker')
        },
        onConfirm(e) {
            this.$emit('onConfirm', this.pickerValue)
        },
        onCancel(e) {
            this.$emit('onCancel'}, /** Picker change */ onValuesChange(picker, values) {const pickerValue = values[0] +The '-' + values[1] + The '-' + values[2] + ' ' + values[3]
            this.pickerValue = pickerValue
            this.$emit('onValuesChange'PickerValue)},},} </script> <style scoped> //... </style>Copy the code

Package this component as a plug-in. The format of the vue plug-in is to mount the component through Install, use Vue.component to register a plug-in, and externally use a plug-in. The complete contents of index.js are as follows.

import VueHalfdayDatepicker from './VueHalfdayDatepicker.vue'

const datePicker = {
  install: function(Vue) {
    Vue.component(VueHalfdayDatepicker.name, VueHalfdayDatepicker)
  }
}

// Judgment is important here
if (typeof window! = ='undefined' && window.Vue) { 
  window.Vue.use(datePicker) 
}
export default datePicker
Copy the code

To test the plug-in

How do I test the success of a plug-in development by importing it in main.js as a direct reference to a native plug-in instead of building it directly

import VueHalfdayDatepicker from '.. /dist/vue-halfday-datepicker.js'
Vue.use(VueHalfdayDatepicker)
Copy the code

Use components in app.vue

<template> <div id="app"> <h2> A VUE based date picker Demo</h2> <div class="pickerSelect" @click="onOpenPicker">{{pickerValue }}</div> <vue-halfday-datepicker :show="isShow" @onConfirm="onConfirmHandle" @onCancel="onCancelHandle"/> </div> </template> <script> export default { name: 'app', data () { return { isShow: false, pickerValue: 'Test: select'}}, methods: { onOpenPicker(e) { this.isShow = true }, onConfirmHandle(v) { this.value = v this.pickerValue = v this.isShow = false }, OnCancelHandle (e) {this.isShow = false}},} </script> <style> //... </style>Copy the code

Execute NPM run dev, then view the plug-in in the page, fix the plug-in bug, etc., view no problems in the page. Then modify the webpack.config.js entry file and the generate file name.

  // entry: './src/main.js'// Page entry:'./src/lib/index.js'Output: {path: path.resolve(__dirname,'./dist'),
    publicPath: '/dist/',
    // filename: 'build.js'// Generate the page from filename:'vue-halfday-datepicker.js'// Plugin generation file libraryTarget:'umd',
    umdNamedDefine: true
},
Copy the code

Execute NPM run build and build the plug-in vue-halfday-datepicker.js in the dist folder. Then configure the build back to the page to see the effect of the plug-in.

Plug-in optimization

A vUE plug-in is basically developed. We want to see the size of each module of the plug-in generated by the build, and what space can be optimized using the visual tool Webpack-Bundle-Analyzer. Use the command line CNPM I webpack-bundle-Analyzer in the project root directory and go to webpack.config.js to configure it

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

plugins: [
    new BundleAnalyzerPlugin()
]
Copy the code

Execute NPM run dev to see the size of each module of the packaged plug-in. We found that the plugin packaged vUE because mint-UI introduced vUE. Plugin size, Parsed size: 161.33 KB.

We configure externals to prevent some import packages from being packaged into the bundle, and instead obtain these extension dependencies externally at runtime. Set externals to prevent the vue package from being packed in. After packing, the plugin package is much smaller (Parsed size: 64.46 KB).

externals: {
    vue: 'Vue'
},
Copy the code

Push to Github and configure demo on GH-Pages

Deploy the DEMO address, come and see the effect.

Github’s git repository is very easy to use, so I will not go into the basic operation of Github. When we push the plugin library to Github, the default is to push it to the master branch. Then we create a branch called GH-Pages, merge the contents of the master branch into the GH-Pages branch, and submit them to the remote branch. Note that the GH-Pages branch is a static website deploiter provided by Github. By default, the gh-Pages branch reads the index.html file in the root directory of the project.


      
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,viewport-fit=cover">
    <title>vue-halfday-datepicker</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script src="./dist/build.js"></script>
  </body>
</html>
Copy the code

Dist /build.js in is the build file of the page. Note that dist is not configured in.gitignore, otherwise the build.js file cannot be read. Deploy the DEMO address, come and see the effect.

Publish plug-ins, publish an NPM package

Wahaha, the last step, let’s see how to publish. If you are familiar with this process, you can fool this module. If this article helps you, please give me a thumbs up. 【 Shameless to attention, to praise, hee hee ~ 】

Register on NPM website

Go to NPM official website to register. When registering, remember your user name, password and email address, which we will use later.

NPM package release

Go back to the repository root of our vue plugin, open the command line, type NPM login, enter your username and password as prompted, and then run NPM publish to publish. The NPM package name and version number are displayed in the command.

During package delivery, if you encounter a small problem that the package has the same name or the version number is not updated, you can search for it and solve it easily.

conclusion

Hope to help you understand the process and ideas of writing plug-ins, you will find that in business travel, sometimes do some business plug-ins can reflect the value of doing business. Go ahead and give it a try. You can write all kinds of widgets, and feel free to talk to me in the comments section.