Asp.net+Vue+EmelentUI的實現(五)全局組件的註冊

Vue註冊全局組件,只要直接註冊即可,代碼如下

Vue.component('name', {
    props: [],
    template:' '
})

如果我們生成一個vue-comment.js的JS文件,並且通過PageBase的自動加載方式來加載,那麼就可以實現自動載入了。在PageBase的載入默認JS的地方,加入載入vue-component.js的代碼,新代碼如下

 /// <summary>
        /// 添加默認的js
        /// </summary>
        private void AddDefaultJs()
        {
            //vue-js
            AddJs("vue.js", "/Scripts/vue.js", "/Scripts/vue.min.js");

            //vue-resource.js
            AddJs("vue-resource.js", "/Scripts/vue-resource.js", "/Scripts/vue-resource.min.js");

            //element-ui.js
            AddJs("element-ui.js", "/Scripts/ElementUI/element-ui.js", "/Scripts/ElementUI/element-ui.js");

            //vue-component.js
            AddJs("vue-component.js", "/Scripts/vue-component.js", "/Scripts/vue-component.js");

            //kit.js
            AddJs("kit.js", "/Scripts/kit.js", "/Scripts/kit.js");

            //global.js
            AddJs("/Scripts/global.js", "/Scripts/global.js", "/Scripts/global.js");

        }

有了vue-component.js,那麼載入了該JS後,Vue組件就實現了全局註冊,但這時又碰到了一個問題,就是這個JS的內容要如何生成?當然了,如果是直接編譯vue-component.js文件是可行的,但是在寫template的時候,由於是使用字符串的拼接,很容易出錯,如果能像vue組件的編寫方式一樣,編寫一個xxx.vue組件,然後通過編譯生成到vue-component.js中,那就會方便很多。但我們採用的是Asp.Net模式來開發,沒有使用nodejs、webpack來編譯打包,所以不能按照常見的加載相關的模塊來編譯打包,爲此,寫了一個簡易的VueEngine來編譯。

VueEngine是一個控制檯程序,代碼如下

    class Program
    {
        static void Main(string[] args)
        {
            var dir = getParentDir(AppDomain.CurrentDomain.BaseDirectory);
            string componentsPath = dir + @"\Components";
            if (!Directory.Exists(componentsPath))
            {
                Console.WriteLine("找不到路徑 " + componentsPath);
                return;
            }
            string vue_component_js = dir + @"\Scripts\vue-component.js";
            StreamWriter streamWriter = null;

            try
            {
                streamWriter = new StreamWriter(vue_component_js, false, Encoding.UTF8);
                var files = Directory.GetFiles(componentsPath, "*.vue");
                if (files == null || files.Length <= 0)
                {
                    Console.WriteLine("沒有文件");
                }
                else
                {
                    var spaces = "    ";
                    foreach (var filePath in files)
                    {
                        StreamReader streamReader = new StreamReader(filePath, Encoding.UTF8);
                        bool isTemplateBegin = false;
                        bool isScriptBegin = false;
                        bool isScriptEnd = false;
                        List<string> templateLines = new List<string>();
                        List<string> scriptLines = new List<string>();
                        while (!streamReader.EndOfStream)
                        {
                            var line = streamReader.ReadLine();
                            if (string.IsNullOrWhiteSpace(line))
                            {
                                continue;
                            }

                            if (!isTemplateBegin && line.Trim().Equals("<template>"))
                            {
                                isTemplateBegin = true;
                            }
                            else if (line.Trim().Equals("<script>"))
                            {
                                isScriptBegin = true;
                            }
                            else if (line.Trim().Equals("</script>"))
                            {
                                isScriptEnd = true;
                            }

                            if (isTemplateBegin && !isScriptBegin)
                            {
                                templateLines.Add(line);
                            }

                            if (isScriptBegin)
                            {
                                scriptLines.Add(line);
                            }

                            if (isScriptEnd)
                            {
                                break;
                            }
                        }

                        if (templateLines.Count > 1)
                        {
                            templateLines.RemoveAt(0);//移除<template>
                            templateLines.RemoveAt(templateLines.Count - 1);//移除</template>
                        }

                        if (scriptLines.Count > 1)
                        {
                            scriptLines.RemoveAt(0);//移除<script>
                            scriptLines.RemoveAt(0);//移除 var exports =
                            scriptLines.RemoveAt(0);//移除 {
                            scriptLines.RemoveAt(scriptLines.Count - 1);//移除</script>
                            scriptLines.RemoveAt(scriptLines.Count - 1);//移除};
                        }
                        //輸出組件名
                        streamWriter.WriteLine("//"+Path.GetFileName(filePath));
                        var nameLine = scriptLines[0];
                        var componentName = nameLine.Substring(scriptLines[0].IndexOf(":") + 1).Replace("'", "").Replace(",", "").Trim();
                        streamWriter.WriteLine($"Vue.component('{componentName}', {{");
                        scriptLines.RemoveAt(0);//移除name行
                        //輸出data props methods等
                        for (int i = 0; i < scriptLines.Count; i++)
                        {
                            var suffix = (i == scriptLines.Count - 1 ? "," : "");
                            var scriptLine = scriptLines[0];
                            if (i == 0)
                            {
                                scriptLine = spaces + scriptLine.TrimStart();
                            }
                            streamWriter.WriteLine(scriptLine + suffix);
                        }
                        //輸出template
                        for (int i = 0; i < templateLines.Count; i++)
                        {
                            var prefix = (i == 0 ? (spaces + "template:'") : "");
                            var suffix = (i == templateLines.Count - 1 ? "'" : @"\");
                            streamWriter.WriteLine(prefix + templateLines[i] + suffix);
                        }
                        streamWriter.WriteLine("})");
                        streamWriter.WriteLine();//添加一行空行,便於與其他組件區分
                    }
                }
                streamWriter.Close();
            }
            catch (Exception ex)
            {
                if (streamWriter != null)
                {
                    streamWriter.Close();
                }
                Console.WriteLine("異常=>" + ex.Message);
            }
        }

        /// <summary>
        /// 獲取上一級目錄
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        private static string getParentDir(string dir)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(dir);
            return directoryInfo.Parent.FullName;
        }
    }

代碼的主要邏輯是衆Components文件夾下讀取所有的.vue後綴的文件,然後對文件分析,提取出template作爲Vue組件註冊的template,然後將Script部分作爲props等,生成vue-component.js文件到Scripts文件夾下。爲了便於解析,我們對原有的vue組件的script定義方式略作了調整,其格式如下

<template>
    <div>
        //組件內容
    </div>
</template>

<script>
    var exports =
    {
        name: 'xxx',
        props: ['x1', 'x2']
    };
</script>

爲了便於編譯,template的開始和結束標記固定佔一行,script的開始和結束標記固定佔一行,script後的一行固定爲var exports=,“{”和“};”固定佔一行。

有了VueEngine後,我們將其輸出到AspNetVueElementUI項目下的VueEngine文件夾,這個需要在VueEngine項目下作設定,對配置的Debug和Release都設置相同的輸出路徑。

這樣設定之後,VueEngine項目編譯的時候,會自動生成到AspNetVueElementUI項目下。

有了VueEngine.exe,那麼我們只要在AspNetVueElementUI項目編譯前先編譯VueEngine,並且調用VueEngine.exe,就可在達成目的了。爲了讓VueEngine先編譯,我們要將VueEngine項目設定爲AspNetVueElementUI的依賴項。在解決方案上右鍵,選擇屬性來設置,如下圖

經過這樣的設定之後,AspNetVueElementUI編譯的時候就會先編譯VueEngine。那我們在AspNetVueElementUI項目上右鍵,選擇屬性來設定,在【生成事件】的生成前事件命令行輸入 ..\VueEngine\VueEngine.exe,如下圖

這時再編譯AspNetVueElementUI項目就會將Components文件夾下的*.vue編譯到vue-component.js下。比如我們在Components添加一個MenuTree.vue

<template>
    <div>
        <template v-for="m in menus">
            <el-submenu :index="m.id" :key="m.id" v-if="m.children&&m.children.length>0">
                <template slot="title">
                    <i :class="m.iconClass"></i>
                    <span slot="title">{{ m.name }}</span>
                </template>
                <menu-tree :menus="m.children" :click="click"></menu-tree>
            </el-submenu>
            <el-menu-item v-else :index="m.id" :key="m.id" @click="click(m.url)">
                <i :class="m.iconClass"></i>
                <span slot="title">{{ m.name }}</span>
            </el-menu-item>
        </template>
    </div>
</template>

<script>
    var exports =
    {
        name: 'menu-tree',
        props: ['menus', 'click']
    };
</script>

然後編譯AspNetVueElementUI項目,MenuTree.vue已經生成到vue-component.js中,代碼如下

//MenuTree.vue
Vue.component('menu-tree', {
    props: ['menus', 'click'],
    template:'    <div>\
        <template v-for="m in menus">\
            <el-submenu :index="m.id" :key="m.id" v-if="m.children&&m.children.length>0">\
                <template slot="title">\
                    <i :class="m.iconClass"></i>\
                    <span slot="title">{{ m.name }}</span>\
                </template>\
                <menu-tree :menus="m.children" :click="click"></menu-tree>\
            </el-submenu>\
            <el-menu-item v-else :index="m.id" :key="m.id" @click="click(m.url)">\
                <i :class="m.iconClass"></i>\
                <span slot="title">{{ m.name }}</span>\
            </el-menu-item>\
        </template>\
    </div>'
})

注意:每行後面的斜扛“\”是換行轉義符,如果不加有的瀏覽器會報錯。

現在我們修改default.aspx生成菜單的部分,代碼如下

 <el-container class="container">
                <el-aside class="left">
                    <el-menu>
                        <menu-tree :menus="menus" :click="open"></menu-tree>                  
                    </el-menu>
                </el-aside>
                <el-main class="right">
                    <iframe style="width:100%; height:100%; border: 0;" :src="iframeUrl"></iframe>
                </el-main>
            </el-container>

利用MenuTree.vue組件生成的菜單如下

源碼下載

轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章