Vue項目入門實例


  前言

  本文記錄Vue2.x + Element-UI + TypeScript語法入門實例

  為什么要用TypeScript?

  1、TypeScript是JavaScript的超集,利用es6語法,實現對js的面向對象編程思想;

  2、TypeScript會像強類型語言一樣,可以避免出現不可預期的運行時bug;

 

  Vue官網:https://cn.vuejs.org/

  Element-UI官網:https://element.eleme.cn/#/zh-CN

 

  2021-03-03更新:

  element-ui已經升級適配vue3,並全新發布新項目:Element Plus

  官網:https://element-plus.gitee.io/#/zh-CN

  GitHub:https://github.com/element-plus/element-plus

 

  Vue對TypeScript的支持:https://cn.vuejs.org/v2/guide/typescript.html

  TypeScript的學習可以看回我們之前的《typescript》系列:https://www.cnblogs.com/huanzi-qch/category/1509796.html

  vue+typescript整合,推薦閱讀這篇文章:https://segmentfault.com/a/1190000011744210

 

  安裝、啟動

  vue項目需要node環境,開始安裝之前,先安裝node環境,安裝node環境看之前的博客:TypeScript環境安裝,以及配置idea開發環境

 

  裝好node環境之后,先安裝Vue CLI手腳架,通過手腳架來快速創建項目

npm install -g @vue/cli

 

  裝好之后使用命令查看版本號,確認一下 

vue --version

 

  裝好了手腳架,然后就可以通過手腳架快速創建portal門戶項目

  PS:element-ui現在還不支持Vue3,所以我們現在Vue2就可以了,選擇自定義安裝把配置項全都勾上,或者可以先選擇默認安裝

vue create portal 

 

  后續再在package.json里面指定依賴包,直接使用IDE(或者手敲命令也一樣),運行安裝命令下載依賴包

 

   package.json依賴配置

  "dependencies": {
    "core-js": "^3.6.5",
    "register-service-worker": "^1.7.1",
    "vue": "^2.6.11",
    "vue-class-component": "^7.2.3",
    "vue-property-decorator": "^8.4.2",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0",
    "axios": "0.21.0",
    "element-ui": "^2.13.2",
    "js-cookie": "2.2.1"
  },

 

  在src的同級目錄下面,創建vue.config.js配置文件,配置端口等

module.exports = {
    publicPath: './',
    outputDir: 'dist',
    assetsDir: 'static',
    lintOnSave: true,
    productionSourceMap: false,
    devServer: {
        port: '10010',
        open: false,
        overlay: {
            warnings: false,
            errors: true
        },
        proxy: {
            '/auth': {
                target: 'http://localhost:10086',
                secure: false,
                changeOrigin: true,
                pathRewrite: {
                    '^/auth': '/'
                }
            },
            '/api': {
                target: 'http://localhost:10086',
                secure: false,
                changeOrigin: true,
                pathRewrite: {
                    '^/api': '/'
                }
            }
        }
    }
}

 

  使用idea打開項目,配置config,即可在idea運行vue項目

 

  或者也可以手動輸入命令啟動項目(vue-cli-service serve),或者在package.json文件中運行腳本

 

  啟動成功

 

  項目結構

 

  Vue Router

  Vue Router官網:https://router.vuejs.org/zh/

  路由配置

import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'

Vue.use(VueRouter);

/* 公用模塊菜單路由 */
const commonRoutes: Array<RouteConfig> = [
    {
        path: '/',
        name: 'Home',
        meta: { title: '主頁' },
        component: () => import( '@/views/Home.vue')
    },
    {
        path: '/404',
        name: '404',
        meta: { title: '404' },
        component: () => import('@/views/common/404.vue')
    },
    { path: '*', redirect: '/404'}
];

/* test模塊菜單路由 */
const testRoutes: Array<RouteConfig> = [
    {
        path: '/test',
        name: 'Test',
        meta: { title: 'demo測試' },
        component: () => import( '@/views/test/Test.vue')
    }
];

const router = new VueRouter({
  base:"/",
  mode: 'hash',//history   hash
  routes:commonRoutes.concat(testRoutes)
});

router.beforeEach(async(to, from, next) => {
    console.log("跳轉開始,目標:"+to.path);
    document.title = `${to.meta.title}`;

    //跳轉頁面
    next();
});

router.afterEach(() => {
    console.log("跳轉結束");

});

export default router

 

  路由跳轉、頁面接參

/**
 * 工具類
 */
export default class CommonUtil {

    /**
     * 從url中獲取參數
     * 實例:http://xxxxx/index?id=1&name=張三
     * getQueryVariable("id")//1
     * getQueryVariable("name")//張三
     */
    public static getQueryVariable(variable:string): string {
        let vars = window.location.search.substring(1).split("&");
        for (let i = 0; i < vars.length; i++) {
            let pair = vars[i].split("=");
            if (pair[0] === variable) {
                return pair[1];
            }
        }
        return "";
    };
}

 

import CommonUtil from  "@/utils/commonUtil"

//跳轉 params 是路由的一部分,必須要有。query 是拼接在url后面的參數,沒有也沒關系
this.$router.push({name:'Home',
    params: {id:'001'},
    query: {id:'001'}
});

//接參
let id = this.$route.params.id;
//如果為空,嘗試從url中獲取參數
if(!id){
    id = CommonUtil.getQueryVariable("id");
}

  或者直接在瀏覽器上輸入path路徑,即可跳轉頁面

 

  Vuex

  Vuex官網:https://vuex.vuejs.org/zh/

  vuex配置

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

/*
  約定,組件不允許直接變更屬於 store 實例的 state,而應執行 action 來分發 (dispatch) 事件通知 store 去改變
 */
export default new Vuex.Store({
  state: {
  },
  getters:{
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

 

  項目入口

  App.vue

<!-- 這里是項目路口,配置<router-view/>即可 -->
<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script lang="ts">

</script>

<style lang="less">
  html,body{
    margin: 0 !important;
    padding: 0 !important;
  }
</style>

 

  main.ts

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// @ts-ignore
import locale from 'element-ui/lib/locale/lang/zh-CN'

Vue.use(ElementUI, { locale });

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app');

 

  TypeScript語法

  Vue對TypeScript的支持:https://cn.vuejs.org/v2/guide/typescript.html

  vue+typescript整合,推薦閱讀這篇文章:https://segmentfault.com/a/1190000011744210

  在使用typescript語法的過程中,我們使用官方維護的 vue-class-component 裝飾器,這里是它的文檔:https://class-component.vuejs.org/

  這個就是它一個簡單的寫法

<template>
  <div>
    簡單頁面
  </div>
</template>

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

@Component
export default class Home extends Vue {

}
</script>

<style scoped>

</style>

 

  完整測試例子

  接下來介紹具體的使用,里面包含了常用的:data 數據、生命周期鈎子函數、methods 普通方法、computed 獲取/設置計算屬性、watch 監聽、props 組件數據傳遞

  HelloWorld組件

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

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

@Component
export default class HelloWorld extends Vue {

  //props 組件數據傳遞
  @Prop({ type: String,default: 'default value' }) private msg!: string;
}
</script>

<style scoped lang="less">

</style>

 

  Test.vue測試頁面

<template>
    <div style="padding: 20px;">
        <el-row>
            <el-col :span="12">
                <div style="padding: 20px;">
                    <el-divider content-position="left">數據綁定測試</el-divider>
                    <el-row>
                        <el-input placeholder="請輸入新msg內容" v-model="msg" clearable></el-input>
                        <p>直接綁定data數據:{{msg}}</p>
                        <p>普通方法獲取data數據:{{getMsg()}}</p>
                        <p>computed的get方法獲取data數據:{{computedTest}}</p>
                        <el-button type="primary" plain @click="buttonClick">調用computed的set方法修改data數據</el-button>
                    </el-row>

                    <el-divider content-position="left">引用HelloWorld組件測試</el-divider>
                    <el-row>
                        <HelloWorld :msg="msg"/>
                    </el-row>

                    <el-divider content-position="left">if-else條件渲染測試</el-divider>
                    <el-row>
                        <p style="color: green" v-if="flag">if條件渲染:true</p>
                        <p style="color: red" v-else="flag">if條件渲染:false</p>
                        <el-button type="primary" plain @click="flag=!flag">if條件渲染取反</el-button>
                    </el-row>
                </div>
            </el-col>
            <el-col :span="12">
                <div style="padding: 20px;">

                    <el-divider content-position="left">for循環-數組渲染測試</el-divider>
                    <el-row>
                        <p v-for="(item,index) in items">
                            序號:{{index}},編號:{{item.id}},姓名:{{item.name}}
                        </p>
                        <el-button type="primary" plain @click="items.push({id:'0000',name:'new item'})">新增記錄</el-button>
                    </el-row>

                    <el-divider content-position="left">for循環-對象渲染測試</el-divider>
                    <el-row>
                        <p v-for="(value,key,index) in itemsByObj">
                            序號:{{index}},{{key}}:{{value}}
                        </p>
                    </el-row>

                </div>
            </el-col>
        </el-row>
    </div>
</template>

<script lang="ts">
    import { Component, Emit, Watch, Prop, Vue } from 'vue-property-decorator';
    import HelloWorld from '@/components/HelloWorld.vue';

    @Component({
        components: {
            HelloWorld,
        },
    })
    export default class Test extends Vue {
        //data 數據
        private msg:string = "test測試";
        private flag:boolean = true;
        private items:any = [
            {id:1001,name:"張三"},
            {id:1002,name:"李四"},
            {id:1002,name:"王五"},
        ];
        private itemsByObj:object = {
            id:1001,
            name:"huanzi-qch",
            age:18,
            email:"huanzi-qch@qq.com",
            phone:"12345678900",
        };

        //生命周期鈎子函數
        created(){
            console.log("created");
        };
        mounted(){
            console.log("mounted");
        };

        //methods 普通方法
        @Emit()
        getMsg(): string{
            return this.msg;
        }
        @Emit()
        buttonClick(): void{
            this.computedTest = 'test測試0001';
        }

        //computed 獲取/設置計算屬性
        get computedTest(): string{
            return this.msg;
        }
        set computedTest(newMsg:string){
            this.msg = newMsg;
        }

        //watch 監聽
        @Watch('msg')
        onMsgChanged(newVal: string, oldVal: string) {
            this.$message.info("msg值發生改變,舊值:" + oldVal + ",新值:" + newVal);
        }
    }
</script>

<style scoped>

</style>

  

  效果演示

  路由配置哪里要注意

  //history:路徑直接是/test,部署到Tomcat后不能直接訪問地址欄
  //hash:路徑會多一層/#/test,部署到Tomcat后能直接訪問地址欄
  mode: 'hash',

 

 

 

  環境配置文件

  配置文件的key,要以VUE_APP_開頭

 

  讀取

<template>
  <div>
    {{adminUrl}}
  </div>
</template>

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

@Component
export default class Home extends Vue {
    //讀取環境配置值
    private adminUrl:string = process.env.VUE_APP_ADMIN_URL;
}
</script>

<style scoped>

</style>

 

  favicon.ico圖標

   通常情況下,我們是這樣設置自己的favicon.ico

  在項目HTML頁面中,引入我們的favicon圖片

 

   但是不管是在運行之后的頁面,還是打包之后的頁面,這行代碼都是被注釋起來的

 

   我們可以再打包生成的index頁面中,把這個注釋放開,這樣就可以正常顯示我們的favicon圖片了

 

  同時、我們可以再vue.config.js中進行設置

  pwa配置項說明:https://cli.vuejs.org/zh/config/#pwa

 

 

 

 

  效果 

 

 

  

  打包、部署

   vue.conifg.js中指定好打包路徑

    publicPath: './',
    outputDir: 'dist',
    assetsDir: 'static',

  同時,路由配置那里要注意,模式要改成mode: 'hash'

const router = new VueRouter({
  base:"/",
  mode: 'hash',//history   hash
  routes:commonRoutes.concat(testRoutes,adminRoutes)
});

 

  直接運行打包腳本,或者手動輸入命令

 

 

   打包成功

 

 

 

  復制dist文件夾到Tomcat容器,把Tomcat運行起來

 

 

 

  訪問:http://172.16.35.52:10086/dist/,即可跳轉到我們配置的 / 路徑頁面

 

  

  在此路徑基礎上就可以訪問我們配置的路由路徑了,如:http://172.16.35.52:10086/dist/#/test

 

  2020-11-20更新

  路由的配置要注意

  //history:路徑直接是/test,文件丟到Tomcat的webapps,文件夾名 + url路徑不能訪問(需要把文件放在ROOT默認文件夾下面)
  //hash:路徑會多一層/#,/#/test,文件丟到Tomcat的webapps,文件夾名 + url路徑能訪問

const router = new VueRouter({
  base:"/portal",
  mode: 'history',
  routes:commonRoutes.concat(testRoutes)
});

  同時要注意,我們在vue.conifg.js中配置的服務信息,依賴node環境,如果是Tomcat,沒有代理功能,需要配合nginx上配置代理地址

    devServer: {
        port: '10010',
        open: false,
        overlay: {
            warnings: false,
            errors: true
        },
        proxy: {
            '/auth': {
                target: 'http://localhost:10086',
                secure: false,
                changeOrigin: true,
                pathRewrite: {
                    '^/auth': '/'
                }
            },
            '/api': {
                target: 'http://localhost:10086',
                secure: false,
                changeOrigin: true,
                pathRewrite: {
                    '^/api': '/'
                }
            }
        }
    }

 

 

 

  后記

  Vue項目入門實例就暫時記錄到這,后續再繼續更新

 

  代碼開源

   注:portal前端就是本文中的vue項目

 

  代碼已經開源、托管到我的GitHub、碼雲:

  GitHub:https://github.com/huanzi-qch/fast-scaffold

  碼雲:https://gitee.com/huanzi-qch/fast-scaffold


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM