分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

自定义视图引擎,实现MVC主题快速切换

发布时间:2023-09-06 02:05责任编辑:沈小雨关键词:MVC

一个网站的主题包括布局,色调,内容展示等,每种主题在某些方面应该或多或少不一样的,否则就不能称之为不同的主题了。每一个网站至少都有一个主题,我这里称之为默认主题,也就是我们平常开发设计网站时的一个固定布局,固定色调,固定内容展示等构成一个默认的固定主题。单一主题针对一些小网站或网站用户群体相对单一固定还是比较适用的,但如果是大型网站或是网站的用户群体比较多而且复杂,如:京东,博客园里的每个博客空间、文俊IT社区网(我的网站,虽不是大型网站,但也实现了主题切换功能的哦!~)等,是需要多个网站主题的,当然我举的这两个网站他们都实现了多主题,比如:

京东默认主题:适合国内人群

英文主题:适合国外人群

博客园就不用在此举例了吧,大家看每个人的博客风格不同就知道了。

上面的表述其作用是为了说明主题对于一个大中型或多种不同用户群体的网站的重要性,而如何实现多种主题的实现与切换也是本文主要说明的。主题的实现与切换方法有很多,常见的方法有:动态替换CSS+JS、ASPX页面可以采取制作多种控件主题进行切换、切换页面路径,不同的路径同页面文件设计成不同的主题等,而我这里要讲解的是MVC下如何实现通过切换路径来实现主题的切换功能。

MVC页面展示的内容来自视图页面(view.cshtml,view.vbhtml),如果说要实现在相同的后台处理代码下,实现不同的主题展示,我们只需要改变视图页面内容就可以了,但默认情况下,一个Action对应一个视图,如何实现一个Action在某种主题下对应不同的的视图文件呢?我这里给出如下两种方案:

第一种方案,很简单,可以根据请求的主题名称来返回不同的视图,代码实现如下:

Action:

1
2
3
4
5
publicActionResult TestCustomViewPath(stringtheme)
{
stringthemeName =string.IsNullOrEmpty(theme) ?"Default": theme;
returnView(themeName +"/Test");//注意这里指定了一相对路径
}

View:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//Default:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
我是自定义的视图路径,风格:@ViewBag.CurrentThemeName
</div>
@using(Html.BeginForm()){
<span>选择主题:</span> @Html.DropDownList("theme",new[] {newSelectListItem() { Text ="默认", Value ="Default"},
newSelectListItem() { Text ="绿色", Value ="Green"}})
<p>
<input type="submit"value="应用"/>
</p>
}
</body>
</html>
//Green:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body style="color:Orange;">
<div>
我是自定义的视图路径,风格:@ViewBag.CurrentThemeName
</div>
@using(Html.BeginForm()){
<span>选择主题:</span> @Html.DropDownList("theme",new[] {newSelectListItem() { Text ="默认", Value ="Default"},
newSelectListItem() { Text ="绿色", Value ="Green"}})
<p>
<input type="submit"value="应用"/>
</p>
}</body>
</html>

注意这里面的视图文件,不再是之前的默认情况,而是如下结构:即:在同一个控制器对应的视图目录下存在多个以主题为名的子目录,子目录中的文件名相同。

实现效果如下图示:

从上面的效果来看,确实已经实现了所谓的主题切换,但这种方法我并不是很推荐,因为视图文件目录过于混乱,每个控制器视图目录下均包含多个主题子目录,且每个子目录下的文件名相同,这让我很难区别,容易出现更错的情况,有人可能会说,我也可以将视图文件名改成不同的呀,比如:Green_Test.cshtml,这样就能区分了,但我仍然说不建议这样做,至少找视图文件都找得麻烦,推荐我下面介绍的第2种方法,具体如何实现,请君往下看。

我们知道,视图如何呈现,或者说如何被解析,均是需要视图引擎ViewEngine来支持的,微软给我们提供了两种视图引擎,即:WebFormViewEngine,对应的视图文件扩展名为:aspx;RazorViewEngine,对应的视图文件扩展名为:cshtml,vbhtml;从如下源代码也可以看出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespaceSystem.Web.Mvc
{
publicstaticclassViewEngines
{
privatestaticreadonlyViewEngineCollection _engines =newViewEngineCollection
{
newWebFormViewEngine(),
newRazorViewEngine()
};
publicstaticViewEngineCollection Engines
{
get
{
returnViewEngines._engines;
}
}
}
}

看到这个代码,我们应该可以看出,可以通过ViewEngines.Engines来添加我们自定义或是第三方的视图引擎(如:Nvelocity),来实现支持不同的视图文件格式,我这里因为目的是需要实现主题切换,所以就来自定义视图引擎,因为视图引擎实现细节比较复杂,若直接继承自IViewEngine接口,需要考虑与实现的代码会比较多且存在风险,所以我是直接继承自RazorViewEngine,既然要实现该类,我们先看一下该类的源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
usingSystem;
usingSystem.Collections.Generic;
namespaceSystem.Web.Mvc
{
publicclassRazorViewEngine : BuildManagerViewEngine
{
internalstaticreadonlystringViewStartFileName ="_ViewStart";
publicRazorViewEngine() :this(null)
{
}
publicRazorViewEngine(IViewPageActivator viewPageActivator) :base(viewPageActivator)
{
base.AreaViewLocationFormats =newstring[]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.vbhtml"
};
base.AreaMasterLocationFormats =newstring[]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.vbhtml"
};
base.AreaPartialViewLocationFormats =newstring[]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.vbhtml"
};
base.ViewLocationFormats =newstring[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
base.MasterLocationFormats =newstring[]
{
我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved