preface

@vue/ CLI V3 has gone through four months of iteration since its inception (currently RC3),

In addition to the terminal initialization pose, a new project initialization pose has been introduced;

Web end initialization, experience, the effect is very good;

The rear many pictures, interested can look, not interested please stop, so as not to waste your time, thank you..

Official website and Installation

  • Official website: Vue Cli

  • Installation: NPM i-g@vue /cli

Regular orders

General Chinese notes below


 Usage: vue <command> [options] options: -v, --version Prints the current scaffold version -h, --help Commands with help: Create [options] <app-name> initialize a project based on vue-cli-service, terminal add <plugin> [pluginOptions] invoke <plugin> [pluginOptions] Activate (invoke) the plugin inspect [options] [paths...] Check the Webpack option in the project serve [options] [Entry] Zero configuration Run the development mode build [options] [Entry] Zero configuration Run the production mode UI [options] The Web interface initializes the project init [options] <template> <app-name> Perform vue < similar to 'vue-cli' to initialize remote templates (need to follow v3 specifications)command> --help for more detailed help with this option.Copy the code

Without further ado, today I just want to demonstrate the Web UI initialization…

The UI initialization

0. Terminal running!!

When the Vue UI is executed on the terminal, localhost:8000 is initialized by default and automatically enabled

Click Create on the top TAB to enter the initialization screen and click Create a new Project here to enter the initialization of the new project

The directories inside can be expanded, similar to the local directory experience, will be iterated out to show

1. Fill in the directory name or something

2. Select a fine-grained configuration

3. Select the item to be enabled

4. Perform further configuration based on the previous step

Finally, click Create Project to perform the operations and install the corresponding dependencies

In fact, the terminal is executing, but the page also shows you some effects, a mask loading layer and some text

5. There will be a management background after creation… Pretty cool..

Plug-in library

This is really practical, for the expansion of the project and so on

The development of running

Detailed record of module size, this is the analysis of the plug-in display… This makes writing code more aware of the size of the project

In addition, tasks can also configure the domain name to access, whether to enable HTTPS, and the corresponding development mode

6. Plug-ins update intuitive experience

Some updates have an exclamation mark indicating that the version may be unstable, as shown in the figure

Click update to display a mask layer, that is, the terminal is installed;

7. Visualization of project configuration

At present, I have seen that this section is still not perfect. What needs to be configured in detail is to read the official scaffolding document and write a vue.config.js.

I’ll do it a little bit later, but it’s easy

The vue-cli 3 configuration file introduces the concept of a global configuration file, creating a new vue.config.js in the root directory,

For example, reverse proxy for our most commonly used interface, multithreaded compilation (speed up compilation only if the kernel is greater than 1)

  • vue.config.js

module.exports = {
  devServer: {
    proxy: {
      '/': {
        target: 'xxx'
        changeOrigin: true
        // pathRewrite: {
        // '^/api': '/'
        // }}}},parallel:true};Copy the code

You can also select add-on files such as.babelrc and postcss that are separate from your project initialization and can also be concentrated in package.json

Therefore, the configuration can be divided into three pieces at most and centralized at least

  1. Individual files,.babelrc..postcssrc.js
  2. vue.config.js
  3. package.json

For more configuration, please refer to the official manual: Vue Cli

Writing the demo

Want to know what it looks like in writing…

I took a download page and changed it, and it ran something like this

I will not show the URL of the product, but use XXX

  • AppDownload.vue

<template>
  <div class="page">
    <div class="appicon">
      <img src=".. /.. /assets/share/[email protected]">
      <p>
        <span>The real</span><br>
        <span>Is the best part</span>
      </p>
    </div>
    <wechat-browser-check :check-open="checkBrowser" />
    <a
      :href="downloadUrl"
      class="goto-download"
      @click="checkWXPlatform">{{ storeName }}</a>
  </div>
</template>

<script lang="ts">
    import {Component, Vue} from 'vue-property-decorator';

    import WechatBrowserCheck from '@/components/WechatBrowserCheck.vue';

    import service from '@/api/index.ts';

    const device: any = require('current-device').default;


    @Component({
        components: {
            WechatBrowserCheck,
        },
        metaInfo() {
            return {
                title: 'App Download'.// set a title
                titleTemplate: '%s -  Welcome!'.// title is now "My Example App - Yay!"
                htmlAttrs: {
                    lang: 'zh'}}}})export default class AppDownload extends Vue {

        private checkBrowser: boolean = false;// Check that the browser is running UA
        private downloadUrl: string = ' '; // Download the link
        private storeName: string = 'the APP download'; // Store name
        private country: string = 'CN' / / country

        created() {
            // On PC
            if (device.desktop()) {
                window.location.href = 'xxx';
            }
            this.fetchBasicInfo();
        }

        checkWXPlatform():void {
            this.checkBrowser = true;
        }

        async fetchBasicInfo() {
            try {
                const [
                    country = 'CN',
                    downloadUrl = 'xxx'
                ] = await Promise.all([
                    service
                        .get('/country')
                        .then((res: any) = > res.state === 200 && res.data),
                    service
                        .get('/android_v')
                        .then((res: any) = > res.state === 200 && res.data.android_apk_url)
                ]);
                this.getMobileApp(country, downloadUrl);
            } catch (error) {
                console.log('Network error');
            }
        }

        getMobileApp(country: string, downloadUrl: string): void {
            if (device.ios() || device.ipad() || device.iphone()) {
                country === 'CN'
                    ? (this.storeName = 'to download the IOS')
                    : (this.storeName = 'App Store');
                this.downloadUrl =
                    'xxx';
            }

            // Get the download link
            if (
                device.android() ||
                device.androidPhone() ||
                device.androidTablet()
            ) {
                this.country === 'CN'
                    ? (this.storeName = 'Android')
                    : (this.storeName = 'Google Play');
                this.downloadUrl = downloadUrl; }}}</script>

<style scoped lang="scss">.page { position: relative; -webkit-overflow-scrolling: touch; height: 100%; background: url(.. /.. /assets/share/mountainWater.png) no-repeat left top; background-size: cover; .appicon { position: absolute; top: 65px; left: 56px; width: 251px; img { display: block; width: 150px; height: 150px; border-radius: 22px; Box-shadow: 0 0 1px rgba(32, 89, 138, 0.31); } p { margin: 35px 0; text-align: left; letter-spacing: 1px; color: #205b8a; font-size: 24px; font-weight: 600; font-stretch: normal; line-height: 15px; > span { display: block; padding: 5px 0; white-space: nowrap; } } } .goto-download { position: absolute; z-index: 3; bottom: 81px; left: 50%; display: block; width: 638px; height: 87px; transform: translateX(-50%); text-align: center; text-decoration: none; color: #fff; border-radius: 100px; background: rgba(70, 55, 61, 1); box-shadow: #000 0 2px 4px; font-size: 32px; line-height: 87px; }}</style>

Copy the code
  • WechatBrowserCheck.vue

<template>
    <div v-if="showIntro"
         class="intro-layer">
        <div class="desrc">
            <p class="desrc-tips">Please click on the upper right corner to open the browser, thank you!</p>
        </div>
    </div>
</template>

<script lang="ts">

    import {Component, Emit, Model, Prop, Vue, Watch} from 'vue-property-decorator'

    @Component({})
    export default class WechatBrowserCheck extends Vue {
        private deviceType: string = ' '; // Device type
        private showIntro: boolean = false;


        @Prop({default: 'wechat'}) types! :String;

        @Prop({default: false}) checkOpen! :Boolean;

        @Watch('checkOpen')
        oncheckOpenChanged(val: string, oldVal: string) {
            if (val) {
                this.openAlert();
            }
        }


        openAlert() {
            if (this.checkOpen) {
                if (Array.isArray(this.types)) {
                    this.types.map(item= > {
                        if (item === this.deviceEnvCheck()) {
                            this.showIntro = true;
                        }
                        return item;
                    });
                } else {
                    this.deviceEnvCheck() === this.types
                        ? (this.showIntro = true)
                        : (this.showIntro = false);
                }
                console.log('deviceType:' + this.deviceEnvCheck(), 'types:' + this.types);
            }
        }

        deviceEnvCheck() {
            // Check the type of device that needs to pop up
            // Get the accessed user-agent
            let ua: string = navigator.userAgent.toLowerCase() || window.navigator.userAgent.toLowerCase();

            if (/MicroMessenger/gi.test(ua)) {
                return 'wechat';
            }
            if (/WeiBo/gi.test(ua)) {
                return 'weibo';
            }
            if (/QQ/gi.test(ua)) {
                return 'qq';
            }
            if (/(iPhone|iPad|iPod|iOS)/gi.test(ua)) {
                return 'ios'; }}};</script>

<style lang="scss" scoped>.intro-layer { position: fixed; z-index: 9999; top: 0; left: 0; width: 100%; height: 100%; background-color: #f2f2f2; background-image: url(.. /assets/share/openbrowser.png); background-repeat: no-repeat; background-position: center 80px; background-size: 100% auto; .desrc { width: 90%; height: auto; margin: 10px auto; padding: 10px; border-radius: 10px; background-color: #fff; .desrc-tips { font-size: 15px; }}}</style>


Copy the code

At present, the coding experience is not good, and the peripheral library is not perfect, which needs to be improved for a period of iteration;

The current class writing style relies on vue-class-Component implementation [decorator]

Some features (prop,watch, etc.) also rely on a library vue-property-decorator

The JSX integration was not complete, requiring some compromises, and was also different from the React JSX

conclusion

The overall feeling is good, and it feels like other scaffolds will introduce this kind of WEB UI in the future, greatly improving the experience;

For now, however, the experience of using TS + decorator with Vue is not very good, due to some bugs.

The JSX support is not perfect and differs from the React JSX

By far the best combination of TS + decorators is Angular, introduced in NG2 and now in NG6;

If there is something wrong, please leave a message and correct it in time. Thank you for reading