整合TypeScript Vue.JS與ASP.NET Core網站應用程式

by vivid 17. 四月 2019 06:09

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:
N190420602
出刊日期: 2019/4/17

在這篇文章中,將要介紹如何透過Visual Studio Code開發工具,使用TypeScript物件導向語法,搭配Vue.JS來撰寫ASP.NET Core 網站應用程式,並利用Webpack來自動打包與壓縮生產環境所需的JavaScript與CSS檔案。

在開始這篇文章的設計步驟之前,你的環境要先安裝好Node.Js、NPM 、ASP.NET Core與Visual Studio Code開發環境。

 

安裝AspNetCore SpaTemplates樣版專案

我們可以先從安裝微軟(Microsoft)提供的單一網頁應用程式 (Single Page Application templates)樣版開始。首先在命令提示字元中,輸入以下的指令,以便從網路安裝AspNetCore的樣版專案:

dotnet new -i Microsoft.AspNetCore.SpaTemplates

這個命令執行結果,請參考下圖所示:

clip_image002

圖 1:安裝「SpaTemplates」樣版。

完成後,會自動表列出可用的樣版專案清單,或者你也可以在命令提示字元中輸入以下指令,來表列出目前安裝的樣版清單:

dotnet new -l

表列的結果請參考下圖所示,其中有包含Vue.js樣版專案(ASP.NET Core with Vue.js):

clip_image004

圖 2:樣版專案清單。

接著在命令提示字元輸入以下的指令,先使用「mkdir」指令建立一個「VueTSCore」資料夾,再利用「cd」將工作路徑切換到新建立的「VueTSCore」資料夾,然後利用「dotnet new vue」指令建立一個「ASP.NET Core with Vue.js」樣版專案:

mkdir VueTSCore

cd VueTSCore

dotnet new vue

這個命令執行結果,請參考下圖所示:

clip_image006

圖 3:建立「ASP.NET Core with Vue.js」樣版專案。

接著在命令提示字元,切換到專案根資料夾,然後輸入以下的指令,使用「npm」安裝所有相依的程式模組:

npm install

完成之後,套件檔案會放在「node_modules」資料夾下,而「package.json」檔案將記錄安裝的套件與版版資料,其內容大致如下:

{
  "name": " VueTSCore",
  "private": true,
  "version": "0.0.0",
  "devDependencies": {
    "@types/webpack-env": "^1.13.0",
    "aspnet-webpack": "^2.0.1",
    "awesome-typescript-loader": "^3.0.0",
    "bootstrap": "^3.3.6",
    "css-loader": "^0.25.0",
    "event-source-polyfill": "^0.0.7",
    "extract-text-webpack-plugin": "^2.0.0-rc",
    "file-loader": "^0.9.0",
    "isomorphic-fetch": "^2.2.1",
    "jquery": "^3.1.1",
    "style-loader": "^0.13.1",
    "typescript": "^2.2.1",
    "url-loader": "^0.5.7",
    "vue": "^2.2.2",
    "vue-loader": "^11.1.4",
    "vue-property-decorator": "^5.0.1",
    "vue-router": "^2.3.0",
    "vue-template-compiler": "^2.2.2",
    "webpack": "^2.2.0",
    "webpack-hot-middleware": "^2.12.2"
  }
}

接著在命令提示字元,輸入以下指令:

dotnet run

接著便會啟動Asp.NET Core網站,預設會監聽在「5000」埠,請參考下圖所示:

clip_image008

圖 4:啟動Asp.NET Core網站。

開啟瀏覽器,在網址列輸入以下網址:

http://localhost:5000

預設將會看到範本專案的首頁,請參考下圖所示:

clip_image010

圖 5:ASP.NET Core Vue.js範本專案首頁。

使用Visual Studo Code開發工具來開啟這個專案,在命令提示字元,專案根目錄下,輸入以下指令:

Code .

這個樣版專案包含了伺服端的ASP.NET Core程式碼,前端則使用Vue.js與TypeScript進行開發。樣式套用Bootstrap v3.3.7版,並利用Webpack來打包JavaScript與CSS樣式表。檢視目前專案中的檔案,其中「ClientApp」資料夾下的「boot.ts」檔案是Vue.js用戶端程式碼的進入點,目前檔案中的程式碼看起來如下,定義了路由相關資料,註冊元件,以及啟動Vue應用程式的程式碼:

import './css/site.css';
import 'bootstrap';
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);

const routes = [
    { path: '/', component: require( './components/home/home.vue.html' ) },
    { path: '/counter', component: require( './components/counter/counter.vue.html' ) },
    { path: '/fetchdata', component: require( './components/fetchdata/fetchdata.vue.html' ) }
];

new Vue({
    el: '#app-root',
    router: new VueRouter( { mode: 'history', routes: routes } ),
    render: h => h( require( './components/app/app.vue.html' ) )
});

而專案根資料下「webpack.config.js」檔案中的「entry」屬性設定打包完的JavaScript程式名稱為「main」,而「output」屬性指定了JavaScript檔案要儲存的資料夾以及檔案名稱:

const path = require( 'path' );
const webpack = require( 'webpack' );
const ExtractTextPlugin = require( 'extract-text-webpack-plugin' );
const CheckerPlugin = require( 'awesome-typescript-loader' ).CheckerPlugin;
const bundleOutputDir = './wwwroot/dist';

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);

    return [{
        stats: { modules: false },
        context: __dirname,
        resolve: { extensions: [ '.js', '.ts' ] },
        entry: { 'main': './ClientApp/boot.ts' },
        module: {
            rules: [
                { test: /\.vue\.html$/, include: /ClientApp/, loader: 'vue-loader', options: { loaders: { js: 'awesome-typescript-loader?silent=true' } } },
                { test: /\.ts$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
                { test: /\.css$/, use: isDevBuild ? [ 'style-loader', 'css-loader' ] : ExtractTextPlugin.extract({ use: 'css-loader?minimize' }) },
                { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
            ]
        },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: '[name].js',
            publicPath: 'dist/'
        },
        plugins: [
            new CheckerPlugin(),
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify(isDevBuild ? 'development' : 'production')
                }
            }),
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./wwwroot/dist/vendor-manifest.json')
            })
        ].concat(isDevBuild ? [
            // Plugins that apply in development builds only
            new webpack.SourceMapDevToolPlugin({
                filename: '[file].map', // Remove this line if you prefer inline source maps
                moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
            })
        ] : [
            // Plugins that apply in production builds only
            new webpack.optimize.UglifyJsPlugin(),
            new ExtractTextPlugin('site.css')
        ])
    }];
};

安裝「axios」套件

接下來讓我們來看看用戶端開發的步驟,本文將利用「axios」套件送出HTTP請求,叫用ASP.NET Core Web API取得員工清單資料,以顯示在網頁之中。Vue提供了「axios」套件,以便讓你更容易的叫用Web API,我們先來安裝這個套件。切換到命令提示字元,在專案根目錄,輸入以下指令:

npm install axios –save

完成之後,「package.json」檔案內容大致如下:

{
  "name": "VueTSCore",
  "private": true,
  "version": "0.0.0",
  "devDependencies": {
    "@types/webpack-env": "^1.13.0",
    "aspnet-webpack": "^2.0.1",
    "awesome-typescript-loader": "^3.0.0",
    "bootstrap": "^3.3.6",
    "css-loader": "^0.25.0",
    "event-source-polyfill": "^0.0.7",
    "extract-text-webpack-plugin": "^2.0.0-rc",
    "file-loader": "^0.9.0",
    "isomorphic-fetch": "^2.2.1",
    "jquery": "^3.1.1",
    "style-loader": "^0.13.1",
    "typescript": "^2.2.1",
    "url-loader": "^0.5.7",
    "vue": "^2.2.2",
    "vue-loader": "^11.1.4",
    "vue-property-decorator": "^5.0.1",
    "vue-router": "^2.3.0",
    "vue-template-compiler": "^2.2.2",
    "webpack": "^2.2.0",
    "webpack-hot-middleware": "^2.12.2"
  },
  "dependencies": {
    "axios": "^0.18.0"
  }
}

修改「tsconfig.json」檔案組態設定

接著修改「tsconfig.json」檔案,設定「strictFunctionTypes」為「False」,關閉嚴格函式型別檢查模式。

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "module": "es2015",
    "moduleResolution": "node",
    "target": "es5",
    "sourceMap": true,
    "skipDefaultLibCheck": true,
    "strict": true,
    "strictFunctionTypes": false,
    "types": ["webpack-env"]
  },
  "exclude": [
      "bin",
      "node_modules"
  ]
}

加入Vue Page

利用命令提示字元,或利用Visual Studio Code開發工具,在「component」資料夾下,新增一個「employee」資料夾,若要利用Visual Studio Code開發工具,請點選「New Folder」圖示,請參考下圖所示:

clip_image012

圖 6:建立「employee」資料夾。

在「employee」資料夾,加入一個「employee.ts」檔案,若要利用Visual Studio Code開發工具,請點選「New File」圖示,請參考下圖所示:

clip_image014

圖 7:加入一個新檔案。

 

修改employee」資料夾下的「employee.ts」檔案,加入以下程式碼:

import Vue from "vue";
import { Component } from "vue-property-decorator";
import axios from 'axios';
@Component
export default class EmployeeComponent extends Vue {
  dataList: string[] = [];
  mounted() {
    fetch( '/api/values' )
    .then( response => response.json() as Promise<string[]> )
    .then( data => {
        this.dataList = data;
    });
  }
}

 

在「employee」資料夾,加入一個新的「employee.vue.html」檔案,然後在檔案中加入以下程式碼,將取回的員工名稱陣列顯示出來:

<template>
  <div>
    <h1>
      Employee
    </h1>
    <table id="mytable" class="table table-bordred table-striped">
      <thead>
        <th> No. </th>
        <th> Employee Name </th>
      </thead>
      <tbody>
        <tr v-for=" (s, index) in dataList ">
          <td> {{index + 1}} </td>
          <td> {{s}} </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script src = "./employee.ts"></script>

 

修改「ClientApp」資料夾下的「boot.ts」檔案,加入以下程式碼,設定一個新路由:「/employee」,以便存取員工清單頁:

import './css/site.css';
import 'bootstrap';
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);

const routes = [
    { path: '/', component: require( './components/home/home.vue.html' ) },
    { path: '/counter', component: require( './components/counter/counter.vue.html' ) },
    { path: '/fetchdata', component: require( './components/fetchdata/fetchdata.vue.html' ) },
    { path: '/employee', component: require('./components/employee/employee.vue.html') }
];

new Vue({
    el: '#app-root',
    router: new VueRouter( { mode: 'history', routes: routes } ),
    render: h => h( require( './components/app/app.vue.html' ) )
});


修改「components\navmenu」資料夾「navmenu.vue.html」檔案,加入一個選單選項,以便在首頁透過選單來存取到員工清單網頁:

<template>
    <div class = "main-nav">
        <div class = "navbar navbar-inverse">
            <div class = "navbar-header">
                <button type = "button" class = "navbar-toggle" data-toggle = "collapse" data-target = ".navbar-collapse">
                    <span class = "sr-only"> Toggle navigation </span>
                    <span class = "icon-bar"> </span>
                    <span class = "icon-bar"> </span>
                    <span class = "icon-bar"> </span>
                </button>
                <a class = "navbar-brand" href = "/"> VueTSCore </a>
            </div>
            <div class = "clearfix"> </div>
            <div class = "navbar-collapse collapse">
                <ul class = "nav navbar-nav">
                    <li>
                        <router-link to = "/" :exact = "true">
                            <span class = "glyphicon glyphicon-home"> </span> Home
                        </router-link>
                    </li>
                    <li>
                        <router-link to = "/counter">
                            <span class = "glyphicon glyphicon-education"> </span> Counter
                        </router-link>
                    </li>
                    <li>
                        <router-link to = "/fetchdata">
                            <span class = "glyphicon glyphicon-th-list"> </span> Fetch data
                        </router-link>
                    </li>
                    <li>
                        <router-link to = "/employee">
                            <span class = "glyphicon glyphicon-list-alt"> </span> Employee
                        </router-link>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</template>

<style src = "./navmenu.css" />

用戶端的程式碼大致設計完成,最後我們來撰寫伺服端ASP.NET Core Web API的程式碼。

 

撰寫ASP.NET Core Web API伺服端程式碼

我們使用的這個樣版專案包含了伺服端的ASP.NET Core程式碼,在「Controllers」資料夾加入一個新檔案,命名為「ValuesController.cs」,然後在其中加入以下程式碼,叫用「ValuesController」類別中的「Get」方法將回傳字串陣列的資料:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace VueTSCore.Controllers
{
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        [HttpGet]
        public IEnumerable<string> Get( ) {
              return new string[] { "Mary" , "Candy" };
        }
    }
}


切換到命令提示字元,在專案根目錄,輸入以下指令,設定ASP.NET Core工作環境為「Development」,然後執行網站:

set ASPNETCORE_ENVIRONMENT=Development

dotnet run

開啟瀏覽器,在網址列輸入以下網址:

http://localhost:5000

預設將會看到範本專案的首頁,左方的選單中多了一個「Employee」選項,點選之後,右方將顯示取回的員工清單。請參考下圖所示:

clip_image016

圖 8:使用Vue顯示員工清單。

使用Vue.js樣版專案(ASP.NET Core with Vue.js)建立的專案,在開發環境中,你不需要手動執行「webpack」來打包程式。後續只要程式有修改,只要將檔案存檔之後,下次執行網站用用程式,就會自動建置Vue程式碼,並且自動更新畫面。這是因為在專案的「Startup.cs」檔案中,叫用了「UseWebpackDevMiddleware」方法,啟用「Webpack dev 中介軟體」的緣故,參考以下「Startup.cs」程式碼。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.SpaServices.Webpack;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace VueTSCore
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseWebpackDevMiddleware( new WebpackDevMiddlewareOptions
                {
                    HotModuleReplacement = true
                } );
            }
            else
            {
                app.UseExceptionHandler( "/Home/Error" );
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" } );
            });
        }
    }
}

打包完的程式將會放在「wwwroot\dist」資料夾下,名稱為「main.js」檔案,請參考下圖所示:

clip_image018

圖 9:打包完的「main.js」檔案。

Tags:

.NET Core | .NET Magazine國際中文電子雜誌 | ASP.NET Core MVC | TypeScript | Visual Studio Code

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List