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组件生成的菜单如下
转载请注明出处。