筆記:Vue 使用pug + ts

阿賀呀發表於2019-03-06

Vue大操練

技術棧:pug + typescript

專案前景:在前幾天看到別人家的專案使用了pug + ts,總共程式碼行數加起來簡直少的可憐,心癢癢便自己動手試了一試

解決的問題:檢視層的文字資訊完全和頁面解耦,不用擔心找一個欄位/莫名其妙標點的文字錯誤啦,加上ts以後報錯資訊也更多了呢(編譯不通過你丫咋執行!)

  • 語法介紹

    • pug

      使用縮排進行分組,無標籤化

      • .p(v-mode="myModel") ==> <div class="p" v-mode="myModel"></div>
      • .p Hello world! ==> <div class="p">Hello world!</div>
    • Typescript

      使用class語法進行編寫,比js更加嚴謹

  • 專案搭建

    vue-cli3

      選擇manually
    複製程式碼

筆記:Vue 使用pug + ts

    選擇對應的專案需要 (空格選擇)
    - Ts
    - Router
    - Vuex
    - CSS Pre-pro
複製程式碼

筆記:Vue 使用pug + ts

  • 新增pug-loader yarn add pug pug-loader
  • 新增sass-loader yarn add sass-loader node-sass style-loader
  • 目錄結構
    • _constants

      存放一些常量

    • _models

      用來存放頁面的文字資訊、和後臺互動的表單欄位(bean)的封裝類

    • _helpers

      用來存放一些幫助類

    • _services

      編寫獲取頁面資料/呼叫後臺api的封裝類

    • assets

      資原始檔

    • view

      檢視層

  • App.vue

    Component裝飾器為元件新增了生命週期等

<template lang="pug">
 #app
   NavComponent(:json="nav")
   #main
     router-view
</template>

<script lang='ts'>
import { Component, Prop, Vue } from 'vue-property-decorator';
import NavComponent from '@/components/Nav.vue';
import { NavService } from '@/_services';
import { Nav as NavBean } from '@/_models';

@Component({
 components: {
   NavComponent,
 },
})
export default class App extends Vue {
 public nav!: object;
 public data() {
   return {
     nav: {},
   };
 }

 private beforeMount(): void {
   NavService.get().then((res: NavBean): void => {
       this.nav = res;
     });
 }
}

</script>

<style lang="scss">
*{
 font-family: "DIN Pro", "PingFang SC", "Microsoft Yahei", 微軟雅黑;
}

#app {
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 color: #2c3e50;
}

body{
 position: relative;
 margin: 0 !important;
 padding: 0;
 height: 100vh;
}

</style>
複製程式碼
  • Nav.vue
<template lang="pug">
  .nav-wrapper
    img(:src="json.logo")
</template>
<script lang="ts">
import { Vue, Prop, Component } from 'vue-property-decorator';
import { NavService } from '@/_services';
import { Nav as NavBean } from '@/_models';

@Component
export default class Nav extends Vue {
  @Prop() public json?: NavBean;
}

</script>
<style lang="scss">
.nav-wrapper {
  width: 100%;
  height: 60px;
  padding: 10px;
  box-sizing: border-box;
  img {
    height: 100%;
    width: 120px;
  }
}
</style>

複製程式碼
  • NavService
import axios from 'axios';
import { BaseService } from './base.services';
import { Ressource } from '../_helpers';
import { Nav } from '@/_models';

export class NavService extends BaseService {
  public static get(): Promise<Nav> {
    const ressource = new Ressource(process.env.VUE_APP_LOCALURL_ENV);
    ressource.shapeUrl('/content/nav.json', []);
    return axios.get<Nav>(ressource.fullUrl, this.requestOptionsGet())
      .then((data: any) => {
        return data.data;
      });
  }
}

複製程式碼
  • BaseService

export class BaseService {
  public static basicOptions: any = {
    cache: 'no-cache',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer test',
      'Access-Control-Allow-Origin': '*',
    },
    redirect: 'follow',
    referrer: 'no-referrer',
    crossdomain: true,
  };

  public static requestOptionsPost(body: any): object {
    const header: any = {
      ...this.basicOptions,
      ...{
        body: JSON.stringify(body),
      },
    };
    return header;
  }

  public static requestOptionsGet(): object {
    const header: any = {
      ...this.basicOptions,
      ...{
        method: 'GET',
        responseType: 'json',
      },
    };
    return header;
  }

  public static requestOptionsGetAuth(): object {
    return {
      method: 'GET',
    };
  }
}

複製程式碼
  • Index.tsx _services/index.tsx

負責把所有Service匯出

/**
 * suffix rule:
 * 1. (xxx.services.tsx) services which means the class was build for call backend service etc
 * 2. (xxx.page.tsx)     page which means the class was build for the static page text
 * 3. (xxx.tsx)          non-suffix which means the class was build for extra service
 */

export { NavService } from './nav.page';

複製程式碼
  • nav.json public/content/nav.json
{
  "id": 1,
  "name": "xxx-nav",
  "logo": "/img/logo.png"
}
複製程式碼
  • TS語法補充

    • Watch使用
      @Watch('enable')
      private onPropertyChanged(value: any, oldValue: any): void {
        if (value) {
            console.log('value changed!')
        }
      }
    複製程式碼
    • Computed使用

      使用get構造器

      get confirmBtnStyle() {
        if (this.confirmBtnDisable) {
           return {
            'background-color': '#868d90',
            'cursor': 'not-allowed',
          };
        } else {
          return {};
        }
      }
    複製程式碼
    • Emit使用
      @Emit('show')
      private handleShow(): void {}
    複製程式碼

    ?快去試一試吧!

相關文章