Vue 折騰記 - (11) @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

CRPER發表於2018-06-16

前言

@vue/cli v3從開始到現在已經經歷了四個月的迭代(目前RC3),

除了終端初始化的姿勢,還引入了一個新的專案初始化姿勢;

Web端的初始化,體驗了一下,效果很不錯;

後方多圖,感興趣的可以瞧瞧,不感興趣的請止步,免得浪費你的時間,謝謝..


官網及安裝

  • 官網 : Vue Cli

  • 安裝:npm i -g @vue/cli


常規命令

大體中文註釋下


 Usage: vue <command> [options]

  Options:

    -V, --version                         輸出當前腳手架版本
    -h, --help                            使用幫助

  Commands:

    create [options] <app-name>           基於vue-cli-service初始化一個專案,終端 
    add <plugin> [pluginOptions]          新增外掛到該專案
    invoke <plugin> [pluginOptions]       在專案中啟用(呼叫)外掛
    inspect [options] [paths...]          檢查專案中的webpack選項
    serve [options] [entry]               零配置執行開發模式
    build [options] [entry]               零配置執行生產模式
    ui [options]                          web端介面初始化專案
    init [options] <template> <app-name>  類似`vue-cli`初始化遠端的模板(需要遵循v3規格的)

  執行 vue <command> --help 獲取該選項更詳細的幫助.

複製程式碼

其他不多說,今天只想演示下Web端UI初始化...


UI初始化

0.終端跑起來!!!

在終端執行vue ui, 會預設初始化localhost:8000且自動開啟

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

點選頂部tab的Create進入初始化介面, 點選Create a new project here進入新專案初始化

裡面的目錄都是可以展開的,類似本地目錄的體驗,會遍歷出來展示

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化


1.填寫目錄名什麼的

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化


2.選擇配置的細粒度

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化


3.選擇需要開啟的東東

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化


4.針對上一步的選擇進一步的配置

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

最後點選Create Project就會開始執行相關的操作和安裝對應的依賴了

其實就是終端在執行,只是頁面也會給你看一些效果,一個遮罩層loading和一些文字


5.建立完畢會有一個管理後臺...相當酷炫..

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

外掛庫

這個真的很實用,對於專案的擴充什麼的

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

開發執行

詳細的記錄了模組大小,這是把分析外掛展示出來了...這樣寫程式碼的時候更能感知專案的大小了

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

不僅如此,任務還可以配置訪問的域名,是否開啟https,對應的開發模式

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化


6. 外掛更新直觀體驗

有些更新會有一個感嘆號提示該版本可能不穩定,如圖所示

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

點選更新後顯示一個遮罩層,就是終端在安裝;


7. 專案配置的視覺化

目前這塊我看了下還是不大完善的,需要詳細配置的還是需要閱讀官方腳手架的文件,寫一個vue.config.js,

等會我會稍微點一下,也很容易

Vue 折騰記 - (11)  @Vue/Cli 3.0.0 圖形化專案管理,相當人性化

vue-cli 3的配置檔案引入了一個全域性配置檔案的概念,在根目錄新建一個vue.config.js,

比如我們最常用的介面的反向代理,多執行緒編譯(提升編譯速度,只有當核心大於1的時候)

  • vue.config.js

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

};


複製程式碼

你在專案初始化的還可以選擇.babelrc,postcss這類外掛檔案獨立出來,也能集中在package.json

所以說,配置最多分三塊,最少是集中化

  1. 獨立檔案這類,.babelrc,.postcssrc.js
  2. vue.config.js
  3. package.json

更多的配置請查閱官方手冊: Vue Cli


書寫demo

想知道大概寫起來是什麼樣的麼..

我拿了一個下載頁面來改了改,可以跑起來大概是這樣的

產品的url我就不展示了,統一用xxx

  • AppDownload.vue

<template>
  <div class="page">
    <div class="appicon">
      <img src="../../assets/share/yourAppIcon@2x.png">
      <p>
        <span>真實的
        </span><br>
        <span>才是最精彩的</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;// 檢測瀏覽器執行 UA
        private downloadUrl: string = ''; // 下載連結
        private storeName: string = 'APP 下載'; // 商店名稱
        private country: string = 'CN' // 國家

        created() {
            // 若是 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('網路錯誤');
            }
        }

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

            // 獲取下載連結
            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>

複製程式碼
  • WechatBrowserCheck.vue

<template>
    <div v-if="showIntro"
         class="intro-layer">
        <div class="desrc">
            <p class="desrc-tips">請點選右上角的選擇瀏覽器開啟,謝謝!</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 = ''; // 裝置型別
        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() {
            // 檢測需要彈窗的裝置型別
            // 獲取訪問的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>


複製程式碼

編碼體驗目前來說並不好,周邊庫還不夠完善,需要迭代一段時間才有改善;

目前class書寫風格是依賴vue-class-component來實現[裝飾器]

一些特性(prop,watch這些)也是依賴一個庫vue-property-decorator[裝飾器]

jsx結合的也不是很徹底..需要做一些妥協,和react的jsx也有所差異


總結

總體的感覺是很不錯的,感覺以後其他的腳手架也會引入這類的WEB UI,大大改善了體驗;

不過目前來說,用ts + 裝飾器結合Vue的開發體驗還不是很好,因為有一些BUG...

JSX的支援,並不完善,和reactjsx也有所差異

目前來說ts+裝飾器組合配合最好的是angular, 從ng2開始就引入了,現在都ng6了;

期待Vue及周邊庫下半年的改進..下個月新腳手架應該就正式版了(最晚不過中秋)

相關文章