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組件生成的菜單如下
轉載請註明出處。