<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      .Net Core應用框架Util介紹(三)

        上篇介紹了Util的開發環境,并讓你把Demo運行起來。本文將介紹該Demo的前端Angular運行機制以及目錄結構。

       

      目錄結構

          在VS上打開Util Demo,會看見如下的目錄結構。

        

        現代前端通常采用VS Code開發,不過我們為了使用TagHelper,需要采用VS開發,這為你提供了更多的選擇。 

        你可以將WebApi和Angular應用放在同一個項目中,就像現在看見的那樣。也可以分別把WebApi和Angular應用放到不同項目中。 

        如果你已經習慣了VS Code開發,這同樣沒問題,不過你將放棄TagHelper帶來的強類型代碼提示和編譯時檢查特性。 

        對于Angular,它提供了ng cli命令行工具,你可以用ng cli來創建項目結構。

        前文已簡要介紹了TagHelper,它是用來提升Angular視圖頁面開發效率的利器。為了使用TagHelper,不得不放棄ng cli,因為它不支持在Angular組件上配置服務端動態地址。

        下面介紹這個項目中包含的目錄和文件。

       

      Apis目錄

        這個目錄用來存放Web Api控制器。

        ApplicationController演示了普通CRUD操作,RoleController演示了樹型層次的CRUD操作。

        你暫時不要關心Web Api CRUD操作,我會在后續介紹。

       

       Areas目錄

         用過Asp.Net Mvc的同學可能知道,Areas就是區域,它的作用是提供模塊化管理。我們把不同的模塊用Areas的區域分隔開,這樣在項目規模變大時,還能迅速找到相關頁面。

        與傳統Asp.Net Mvc應用不同,Util的Areas控制器并不進行任何操作,只是簡單的返回視圖頁面,cshtml僅起到代碼生成器的作用。

        一個更好的選擇是使用RazorPage,它把控制器和頁面合并了,將來會使用這種方式。 

      Configs目錄

         你并不需要它,我在Demo中用來放測試配置,項目上我通常把Configs目錄放在應用層類庫。

      Controllers目錄

         Controllers目錄是用來放置與首頁相關的控制器。

      Datas目錄  

        Util引入了DDD經典架構,Datas位于基礎設施層,一些人把它叫倉儲層。

        Datas通常放在單獨的類庫,為了演示簡單,我放在該WEB項目的目錄中。

      DbScripts目錄

        這個目錄提供了Sql Server建庫腳本。

        一些人可能很驚訝,什么年代了,還在使用Db First開發。

        在多年的開發實戰中,我摸索到一套以PowerDesigner數據建模配合CodeSmith代碼生成的開發模式。對于CRUD,它具有快速高效的特點,同時你還能擁有清晰的數據字典以供未來查閱。

        對于具備面向對象編程能力的人,這種方式并不會降低代碼質量和設計水平,在將代碼生成出來以后,通過手工調整就可達到與Code First相同的代碼水平。

        我會在未來某個合適的時候介紹這種開發模式。

       Domains目錄

        DDD經典架構中領域層相關的目錄,實際開發中將放到單獨的類庫。

      Services目錄

        DDD經典架構中應用層相關的目錄,實際開發中將放到單獨的類庫。

      Typings目錄

         Angular相關的所有東西都在這里。

       

        app目錄用來存放與業務相關的項目資源,比如Angular組件,指令,服務等。

        值得注意的是,該目錄包含組件對應的.html文件,這些.html文件和.cshtml文件是怎樣的關系?

       

       

        如果你從未運行過Util Demo項目,打開app目錄,并未找到任何.html文件。

        你可能已經猜到了,.html文件是由.cshtml文件生成的

        你永遠都不應該手工編輯這些.html文件,因為在調試運行時將被覆蓋。 

        test目錄包含Ts單元測試,我僅對極少數Helper進行單元測試。通過下面的npm命令把測試運行起來。

      npm test

       

        util目錄包含對Angular常用API和Angular Material組件的封裝。

        

       

        Angular組件由視圖和控制器兩部分構成。視圖即模板頁,包含html標簽。控制器用來編寫邏輯,包含Ts代碼。換句話說,Angular應用開發主要是編寫html和ts(當然還有css,暫時不要管它)。

        TagHelper并不是Util封裝Angular的唯一手段,對于Angular控制器,Util采用鏈式封裝手法,將Angular常用Api封裝得更加簡單易用,使你對Angular Api只要有一個模糊的印象就可以開發了。

        對于Angular視圖頁面,并不能直接采用TagHelper簡單包裝,這樣會導致TagHelper過于復雜,另外很多功能需要在運行時進行判斷,TagHelper只在開發調試階段存在,所以采用兩層封裝會更加省力。

        首先采用Angular組件或指令對Material組件進行封裝,然后采用TagHelper提供強類型提示。  

        對于希望采用VS Code開發的同學,Typings/util目錄中封裝的代碼同樣可以使用,它跟TagHelper沒有什么關系,你可以把它Copy到你的項目,我尚未把它發布到npm。 

      Views目錄

        Views目錄包含首頁。

      appsettings.json文件

        它是一個配置文件,數據庫連接字符串在這里。

      nlog.config文件

        它是NLog日志組件的配置文件,Util 采用NLog輸出開發調試和錯誤日志,默認位置是c:\log目錄。

      package.json文件

        它是npm包管理器的配置文件。

      Program.cs文件

        它是Asp.Net Core程序入口點文件。

      Startup.cs文件

        它是Asp.Net Core啟動文件,在這里配置依賴注入和中間件請求管道。

      tsconfig.json文件

        它是Typescript語言配置文件。

      webpack.config.js文件

        它是Webpack自動化構建工具的配置文件。

        還有兩個配置文件隱藏在webpack.config.js下,它們對util和第三方Js框架進行處理。

       

      運行機制

        對于沒有前端基礎的同學,可能很難理解這個Demo是如何運行起來的,下面為你介紹這個Demo的運行機制,我們從npm包還原開始。 

       npm還原

        當你輸入yarncnpm install node-sass,它會找到package.json文件的dependencies節,然后把需要的文件下載到node_modules目錄中。

       執行Webpack構建

        然后輸入npm run dev,這里發生了什么?

        npm run是npm的一個命令,它會查找package.jsonscripts定義的命令。

       

      • npm run dev 

        dev就是npm run要查找的命令名,它是一個約定俗成的名稱,代表開發階段配置,即develop,當然你不一定用這個名字,叫abc也可以。

        npm run dev查找到package.json文件scripts節定義的dev命令,它的內容是npm run vendor && npm run app,這個命令是由兩個npm run命令組成的。

      •  npm run vendor

        npm run vendor的內容是webpack --config webpack.config.vendor.js,這將對webpack.config.vendor.js執行構建操作。

        webpack命令默認查找webpack.config.js文件,現在要查找的是webpack.config.vendor.js,所以需要添加參數—config。

        我們來看看webpack.config.vendor.js包含什么內容。 

        1 const pathPlugin = require('path');
        2 const webpack = require('webpack');
        3 var Extract = require("extract-text-webpack-plugin");
        4 
        5 //第三方Js庫
        6 const jsModules = [
        7     'reflect-metadata',
        8     'zone.js',
        9     'moment',
       10     '@angular/animations',
       11     '@angular/common',
       12     '@angular/common/http',
       13     '@angular/compiler',
       14     '@angular/core',
       15     '@angular/forms',
       16     '@angular/elements',
       17     '@angular/platform-browser',
       18     '@angular/platform-browser/animations',
       19     '@angular/platform-browser-dynamic',
       20     '@angular/router',
       21     '@angular/cdk/esm5/collections.es5',
       22     '@angular/flex-layout',
       23     '@angular/material',
       24     'primeng/primeng',
       25     'lodash',
       26     "echarts-ng2"
       27 ];
       28 
       29 //第三方Css庫
       30 const cssModules = [
       31     '@angular/material/prebuilt-themes/indigo-pink.css',
       32     'material-design-icons/iconfont/material-icons.css',
       33     'font-awesome/css/font-awesome.css',
       34     'primeicons/primeicons.css',
       35     'primeng/resources/themes/omega/theme.css',
       36     'primeng/resources/primeng.min.css'
       37 ];
       38 
       39 module.exports = (env) => {
       40     //是否開發環境
       41     const isDev = !(env && env.prod);
       42     const mode = isDev ? "development" : "production";
       43 
       44     //將css提取到單獨文件中
       45     const extractCss = new Extract("vendor.css");
       46 
       47     //獲取路徑
       48     function getPath(path) {
       49         return pathPlugin.join(__dirname, path);
       50     }
       51 
       52     //打包第三方Js庫
       53     let vendorJs = {
       54         mode: mode,
       55         entry: { vendor: jsModules },
       56         output: {
       57             publicPath: 'dist/',
       58             path: getPath("wwwroot/dist"),
       59             filename: "[name].js",
       60             library: '[name]'
       61         },
       62         resolve: {
       63             extensions: ['.js']
       64         },
       65         devtool: "source-map",
       66         plugins: [
       67             new webpack.DllPlugin({
       68                 path: getPath("wwwroot/dist/[name]-manifest.json"),
       69                 name: "[name]"
       70             }),
       71             new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, getPath('./Typings')),
       72             new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, getPath('./Typings')),
       73             new webpack.IgnorePlugin(/^vertx$/)
       74         ]
       75     }
       76 
       77     //打包css
       78     let vendorCss = {
       79         mode: mode,
       80         entry: { vendor: cssModules },
       81         output: {
       82             publicPath: './',
       83             path: getPath("wwwroot/dist"),
       84             filename: "[name].css"
       85         },
       86         devtool: "source-map",
       87         module: {
       88             rules: [
       89                 { test: /\.css$/, use: extractCss.extract({ use: isDev ? 'css-loader' : 'css-loader?minimize' }) },
       90                 {
       91                     test: /\.(png|jpg|gif|woff|woff2|eot|ttf|svg)(\?|$)/, use: {
       92                         loader: 'url-loader',
       93                         options: {
       94                             limit: 20000,
       95                             name: "[name].[ext]",
       96                             outputPath: "images/"
       97                         }
       98                     }
       99                 }
      100             ]
      101         },
      102         plugins: [
      103             extractCss
      104         ]
      105     }
      106     return isDev ? [ vendorJs, vendorCss] : [vendorCss];
      107 }
      webpack.config.vendor.js

        vendorJs 對象用于配置將哪些第三方Js框架文件進行打包,vendorCss 對象用于配置需要打包的第三方框架提供的Css文件。 

        entry屬性指定了需要打包的入口文件,output屬性則指定輸出的位置和文件名。 

        當webpack.config.vendor.js執行完畢,會在Util.Samples.Webs項目的wwwroot目錄創建一個dist子目錄,并生成vendor.jsvendor.css兩個文件。

        注意vendor.js僅在開發調試階段使用,所以并沒有對它進行壓縮,正式發布并不需要執行vendorJs對象。

        該腳本的最后一行證明了這一點。

      return isDev ? [ vendorJs, vendorCss] : [vendorCss];
      •  npm run app 

        npm run app又包含兩個命令,用于執行webpack.config.util.jswebpack.config.js

      webpack --config webpack.config.util.js && webpack

        先來看看webpack.config.util.js

       1 const pathPlugin = require('path');
       2 const webpack = require('webpack');
       3 
       4 module.exports = (env) => {
       5     //是否開發環境
       6     const isDev = !(env && env.prod);
       7     const mode = isDev ? "development" : "production";
       8 
       9     //獲取路徑
      10     function getPath(path) {
      11         return pathPlugin.join(__dirname, path);
      12     }
      13 
      14     //打包util腳本庫
      15     return {
      16         mode: mode,
      17         entry: { util: [getPath("Typings/util/index.ts")] },
      18         output: {
      19             publicPath: 'dist/',
      20             path: getPath("wwwroot/dist"),
      21             filename: "[name].js",
      22             library: '[name]'
      23         },
      24         resolve: {
      25             extensions: ['.js', '.ts']
      26         },
      27         devtool: "source-map",
      28         module: {
      29             rules: [
      30                 { test: /\.ts$/, use: ['awesome-typescript-loader?silent=true'] }
      31             ]
      32         },
      33         plugins: [
      34             new webpack.DllReferencePlugin({
      35                 manifest: require('./wwwroot/dist/vendor-manifest.json')
      36             }),
      37             new webpack.DllPlugin({
      38                 path: getPath("wwwroot/dist/[name]-manifest.json"),
      39                 name: "[name]"
      40             })
      41         ]
      42     }
      43 }
      webpack.config.util.js

        它將查找Util.Samples.Webs項目下Typings/util/index.ts文件,這是util默認導出文件,所有在外部需要訪問的類型都會從這里導出。

        當webpack.config.util.js執行完畢,會在dist目錄創建util.js文件。

        同樣的,util.js文件僅用于開發調試階段 

        下面看webpack.config.js

       1 const pathPlugin = require('path');
       2 const webpack = require('webpack');
       3 var Extract = require("extract-text-webpack-plugin");
       4 const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;
       5 
       6 module.exports = (env) => {
       7     //是否開發環境
       8     const isDev = !(env && env.prod);
       9     const mode = isDev ? "development" : "production";
      10 
      11     //將css提取到單獨文件中
      12     const extractCss = new Extract("app.css");
      13 
      14     //獲取路徑
      15     function getPath(path) {
      16         return pathPlugin.join(__dirname, path);
      17     }
      18 
      19     //打包js
      20     let jsConfig = {
      21         mode: mode,
      22         entry: { app: getPath("Typings/main.ts") },
      23         output: {
      24             publicPath: 'dist/',
      25             path: getPath("wwwroot/dist"),
      26             filename: "[name].js",
      27             chunkFilename: '[id].chunk.js'
      28         },
      29         resolve: {
      30             extensions: ['.js', '.ts']
      31         },
      32         devtool: "source-map",
      33         module: {
      34             rules: [
      35                 { test: /\.ts$/, use: isDev ? ['awesome-typescript-loader?silent=true', 'angular-router-loader'] : ['@ngtools/webpack'] },
      36                 { test: /\.js$/, loader: '@angular-devkit/build-optimizer/webpack-loader', options: { sourceMap: false } },
      37                 { test: /\.html$/, use: 'html-loader?minimize=false' }
      38             ]
      39         },
      40         plugins: [
      41             new webpack.DefinePlugin({
      42                 'process.env': { NODE_ENV: isDev ? JSON.stringify("dev") : JSON.stringify("prod") }
      43             })
      44         ].concat(isDev ? [
      45             new webpack.DllReferencePlugin({
      46                 manifest: require('./wwwroot/dist/vendor-manifest.json')
      47             }),
      48             new webpack.DllReferencePlugin({
      49                 manifest: require('./wwwroot/dist/util-manifest.json')
      50             })
      51         ] : [
      52                 new AngularCompilerPlugin({
      53                     tsConfigPath: 'tsconfig.json',
      54                     entryModule: "Typings/app/app.module#AppModule"
      55                 })
      56             ])
      57     }
      58 
      59     //打包css
      60     let cssConfig = {
      61         mode: mode,
      62         entry: { app: getPath("wwwroot/css/main.scss") },
      63         output: {
      64             publicPath: './',
      65             path: getPath("wwwroot/dist"),
      66             filename: "[name].css"
      67         },
      68         resolve: {
      69             modules: ['wwwroot']
      70         },
      71         devtool: "source-map",
      72         module: {
      73             rules: [
      74                 {
      75                     test: /\.scss$/, use: extractCss.extract({
      76                         use: isDev ? ['css-loader', { loader: 'postcss-loader', options: { plugins: [require('autoprefixer')] } }, 'sass-loader']
      77                             : ['css-loader?minimize', { loader: 'postcss-loader', options: { plugins: [require('autoprefixer')] } }, 'sass-loader']
      78                     })
      79                 },
      80                 {
      81                     test: /\.(png|jpg|gif|woff|woff2|eot|ttf|svg)(\?|$)/, use: {
      82                         loader: 'url-loader',
      83                         options: {
      84                             limit: 20000,
      85                             name: "[name].[ext]",
      86                             outputPath: "images/"
      87                         }
      88                     }
      89                 }
      90             ]
      91         },
      92         plugins: [
      93             extractCss
      94         ]
      95     }
      96     return [jsConfig, cssConfig];
      97 }
      webpack.config.js

        webpack.config.js查找Typings目錄下的main.ts,main.ts是angular項目的入口文件。

        webpack通過遞歸依賴查找main.ts,將除了util.js和vendor.js以外所有引用到的ts或js文件打包到dist/app.js文件中。

        注意,正式發布時,app.js將采用angular官方提供的webpack編譯插件@ngtools/webpack進行AOT編譯并打包生成。

       

        現在dist目錄生成了如下文件。

        0.chunk.js是由angular子模塊生成的js文件,當路由配置對子模塊啟用了延遲加載,每個子模塊都會生成一個獨立的js文件。

       

        loadChildren以延遲加載的方式來配置SystemModule子模塊。

       運行機制

        現在運行angular應用的js文件已經就緒,讓我們把它運行起來,在VS上F5啟動項目。 

        注意:你應該使用Google Chrome來打開它,IE瀏覽器,可以通過啟用polyfill來勉強支持,不過由于效果不佳,我已經把它扔掉了。 

        當瀏覽器打開首頁http://localhost:5200,Asp.Net Core啟動文件Startup.cs中配置的默認路由將被激活,從而將請求發送到HomeController控制器的Index方法。

         Index方法直接返回了Views目錄下Index.cshtml首頁。

       

        environment標簽是一個環境判斷條件,用于設置開發及上線等不同階段的內容。

        <environment include="Development">用于開發階段,<environment exclude="Development">用于發布階段,可以看出,在發布后并不需要vendor.js和util.js文件,因為app.js會包含它們。 

        好,現在瀏覽器加載了Index首頁,Angular應用是如何運行起來的呢?

      • Angular的引導過程

         還記得Angular應用入口文件main.ts嗎,來看看它包含什么內容。

       

        platformBrowserDynamic是為瀏覽器平臺提供的JIT動態編譯服務,它將引導AppModule根模塊的啟動。

        AppModule是Angular應用的根模塊,它的主要任務之一就是啟動AppComponent根組件。

        AppComponent是整個Angular應用的根組件,所有其它組件都將被加載到根組件中。

       

        selector用于指定組件的自定義標簽,這里將根組件標簽定義為<app></app>,你發現它已經被放置在Index.cshtml中。 

        AppComponent根組件準備啟動了,由于是JIT編譯,所以它需要獲取視圖 

        組件的視圖由templateUrl屬性指定。

      templateUrl: env.prod() ? './app.component.html' : '/home/main'

        我們希望開發階段通過訪問服務端控制器來獲取視圖,這樣在編輯TagHelper時就能更方便,只需刷新頁面就能看見效果。 

        env是一個環境檢測對象,prod方法如果返回true表明當前為正式環境,將從app.component.html靜態文件獲取視圖,如果是開發調試環境,則訪問服務端HomeController控制器的Main方法獲取視圖。 

        Main方法上的Html特性,是用來幫助.cshtml生成.html靜態文件的輔助工具。 

        一般情況下,你并不需要手工設置Html特性來生成html文件,Util提供了ViewControllerBase控制器基類,當你的視圖控制器繼承它,所有html文件就會生成到約定的目錄中。

       

        由Template屬性設置的路徑可知,Typings/app中的項目結構也采用模塊化組織,與區域模塊相對應。

         現在來看根組件的視圖。

         這是你第一次看見Util封裝的TagHelper標簽,以<util-打頭的標簽都是Util TagHelper,它們以粗體顯示,這是由于安裝了Resharper的原因。

        TagHelper在運行時會把html輸出到頁面,它們把弱類型的html封裝成了具有強類型提示的標簽。

        如何知道某個TagHelper到底輸出了什么html呢?

        一種辦法是打開它生成的.html文件來查找,不過當頁面很復雜時,這種辦法有點吃力。

        另一種辦法是查看日志,Util TagHelper的每個組件都提供了write-log屬性,當設置為true,就會在C盤log目錄生成日志。

       

        main.cshtml視圖中最關鍵的部分就是<router-outlet></router-outlet>標簽。

        router-outlet是Angular路由的占位符,當根模塊AppModule中配置的路由激活時,相關的Angular組件就會被放進這個占位符中。

        根模塊中的路由配置被拆分到一個單獨的模塊AppRoutingModule中,路由配置如下。

       

        通過路由配置可以發現,當打開首頁時,命中路由第二項path:’’,會跳轉到/systems/application路徑,systems是一個子模塊,我們來查看它的路由配置。

       

       

        /systems/application將激活ApplicationIndexComponent組件,并把它加載到根組件的<router-outlet></router-outlet>中。

        ApplicationIndexComponent組件請求服務端地址/view/systems/application獲取視圖。

       

         /view打頭的地址將匹配到Areas區域控制器,這是在MVC路由配置中設置的。

       

        控制器ApplicationControllerIndex方法將返回視圖。

       

        Angular JIT編譯會在系統啟動時請求服務端URL,在Chrome瀏覽器F12調出開發者工具,刷新頁面,會觀察到頁面請求了Areas中的控制器。

        

        所以你在開發階段運行項目會感覺比較慢,在正式發布后就沒這些開銷了。

      小結  

        本文簡要介紹了Util Demo的目錄結構和運行機制,如果你沒有Angular基礎,估計還是很難看懂,建議你閱讀Angular中文網https://angular.cn  

        未完待續,下一篇將對Util Demo的Angular封裝進行介紹,本來是準備這篇介紹的,不過限于篇幅,放到下篇,我知道,太長的文章既難寫更難讀。

        寫文需要動力,請大家多多支持,點下推薦,Github點下星星。

        Util應用框架交流一群: 24791014

      posted @ 2018-09-17 14:49  何鎮汐  閱讀(8613)  評論(21)    收藏  舉報
      主站蜘蛛池模板: 97久久久精品综合88久久| 国产人成亚洲第一网站在线播放| 国产不卡一区二区四区| 一本高清码二区三区不卡| 91久久偷偷做嫩草影院免费看| 成人精品区| 亚洲国产日韩一区三区| 分宜县| 亚洲精品日本一区二区| 又大又粗欧美成人网站| 亚洲国模精品一区二区| 久久夜色精品国产噜噜亚洲sv| 国产浮力第一页草草影院| 九九综合va免费看| 亚洲男人成人性天堂网站| 亚洲精品岛国片在线观看| 亚洲中文久久久精品无码| 少妇愉情理伦片丰满丰满午夜| 亚洲精品区午夜亚洲精品区| 国产精品爽黄69天堂A| 阳曲县| 国产成人黄色自拍小视频| 给我播放片在线观看| 亚洲在战av极品无码| 镇远县| 欧美成本人视频免费播放| 884aa四虎影成人精品| 日日噜噜夜夜狠狠视频| 久久月本道色综合久久| 国产边打电话边被躁视频| 亚洲AV无码久久精品成人| 久久成人国产精品免费软件| 国产在线一区二区在线视频| 亚洲人成亚洲人成在线观看| 成人精品网一区二区三区| 最近中文字幕日韩有码| 中文字幕人妻精品在线| 国产在线线精品宅男网址| 中文字幕少妇人妻精品| 国产亚洲无线码一区二区| 久久热在线视频精品视频|