开发背景:
最近,领导找我去维护公司里面最古老的项目。由C# MVC框架搭建而成,前后端一起开发,前端由jQuery加一些表单和上传插件开发而成,因为前端写,后端也写,导致代码很乱,一般人不敢去动他。
但是!在这个前后端分离的时代,显然这套框架已经过时了。不说别的,现在一些年纪轻的前端估计都不会jQuery。讲真,我也不想写jQuery.......😥那怎么办呢,得,想办法改造吧!
改造前:
- 第一步:问同事,查资料。得知这个项目基于C# Razor框架开发🚩官方通道。
- 哦吼,刀锋,和摩托罗拉某款手机型号同名。
- 第二步:了解MVC工作原理(
Model+View+Controller
),现在大家喜欢吹的MVVM,早期就是由MVC演变而来,对于正经前端来说,MVC理解起来不难。 - 第三步:看框架,Views+Controllers两个文件夹是核心。
页面渲染的形式,比如 xxx.com/My/Index
通过My找到相应Controller
,然后再通过Index找到对应的方法及return View(Model)
,而这里的Model
会传给Views
,Views
就可以直接用Model
,可能也可以操作Controller
吧,这里就不多做介绍了,毕竟我只是前端。
- 到此,弄明白了完整的
M V C 模 型
!
// /Controllers/MyController.cs
namespace XXX.Web.Controllers{
public class MyController : BaseController
{
#region 构造函数
public MyController(){
// todo something
}
public ActionResult Index(){
// 从数据库获取用户
var userid = LoginContext.Current.UserID;
var model = _TB_UserService.Get(userid);
// 这里把model传给view
return View(model);
}
}
}
// /Views/My/Index.cshtml
@using xxx
@model TB_User
@{
// 配置母板
Layout = "~/Views/Master/_UCLayout.cshtml";
ViewBag.Title = "用户中心";
// 处理model
var UserName = Model.UserName;
}
<style></style>
<div class="UserName">
用户名:@UserName
</div>
<script type="text/javascript">
$(function(){
console.log($('.UserName').text(),"@UserName");
// todo ajax ....
})
</script>
// /Views/Master/_UCLayout.cshtml
@using xxx
@{
var user = LoginContext.Current;
// todo something
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<link rel="stylesheet" href="xxx/global.css?v=@Utils.GetValue("version")" />
<script src="xxxx/jQuery.js?v=@Utils.GetValue("version")"></script>
</head>
<body>
@Html.Partial("_Header")
<div class="Layout">
<!-- 菜单权限 -->
<div class="Menu">
@if (user.IsCa){
<div class="Item">
<a href="/Order/CW">财务菜单</a>
</div>
}
@if (user.UserType == "Person"){
<div class="Item">
<a href="/UserCenter/Person">工作台</a>
</div>
}
@if (user.UserType == "Company"){
<div class="Item">
<a href="/UserCenter/Company">工作台</a>
</div>
}
</div>
<div class="Content">
@RenderBody()
</div>
</div>
@Html.Partial("_Footer")
</body>
</html>
- 以上就是Razor框架的实现流程。
改造难点:
- jQuery要与vue共存,webpack脚手架肯定不可能,那就只能从cdn安装入手。
- 如果页面上要用
el-container
,el-aside
,el-menu
,el-submenu
,el-main
,那么_UCLayout.cshtml
就必须要用Vue加载。- 如果把子页面作为组件,通过
Vue.component('xxx',{})
载入,那新增的需要import到_UCLayout.cshtml
中,太麻烦了。@
在Razor框架中属于关键字,页面上用@click
,会出现异常。- ★★★ 不能影响现有的功能和页面!
改造思路:
方向肯定是:Vue写的母板内嵌Vue写的子页
翻遍了官网文档,脑子浮现一个词:Mixins
灵感往往来自一瞬间🤩
var subApp = {
data(){
return {}
},
methods:{
}
}
var rootApp = new Vue({
el:'#parent',
mixins:[subApp]
})
改造实施:
- 菜单用ElementUI,那就必须先改
_UCLayout.cshtml
// /Views/Master/_UCLayoutVue.cshtml
@using xxx
@{
var user = LoginContext.Current;
// todo something
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<link rel="stylesheet" href="xxx/global.css?v=@Utils.GetValue("version")" />
+ <link rel="stylesheet" href="xxx/ElementUI.css?v=@Utils.GetValue("version")" />
<script src="xxxx/jQuery.js?v=@Utils.GetValue("version")"></script>
+ <script src="xxxx/Vue.js?v=@Utils.GetValue("version")"></script>
+ <script src="xxxx/ElementUI.js?v=@Utils.GetValue("version")"></script>
+ <style>
[v-cloak]{ display: none; }
</style>
+ <script type="text/javascript">
// 核心代码,暂定数组,Header,Footer等都可以混入
var mixinArray = [];
</script>
</head>
<body>
@Html.Partial("_Header")
<el-container class="Layout" id="rootApp" v-cloak>
<!-- 菜单权限 -->
<el-aside width="200px">
<el-menu class="Menu" :default-active="activeIndex">
@if (user.IsCa){
<a href="/Order/CW">
<el-menu-item class="Item">
财务菜单
</el-menu-item>
</a>
}
@if (user.UserType == "Person"){
<a href="/UserCenter/Person">
<el-menu-item class="Item" index="MYINDEX">
工作台
</el-menu-item>
</a>
}
@if (user.UserType == "Company"){
<a href="/UserCenter/Company">
<el-menu-item class="Item" index="MYINDEX">
工作台
</el-menu-item>
</a>
}
</el-menu>
</el-aside>
<el-main class="Content">
@RenderBody()
</el-main>
</el-container>
@Html.Partial("_Footer")
<script type="text/javascript">
var rootApp = new Vue({
el:'#rootApp',
data(){
return {
activeIndex:'MYINDEX',
// ...
}
},
mixins:mixinArray
})
</script>
</body>
</html>
- 子页如果要用vue,那必须不能
var subapp = new Vue();
// /Views/My/IndexVue.cshtml
@using xxx
@model TB_User
@{
// 配置母板
Layout = "~/Views/Master/_UCLayoutVue.cshtml";
ViewBag.Title = "用户中心";
// 处理model
var UserName = Model.UserName;
}
<style></style>
<div class="UserName">
后端用户名:@UserName
前端用户名:{{ UserName }}
<el-button type="primary" @@click="ChangeName">改名</el-button>
</div>
<script type="text/javascript">
var subApp = {
data(){
return {
UserName:'@UserName', // 可设为后端返回的
toggle:false,
}
},
mounted(){
// 打印rootApp,全局vue实例
console.log(rootApp.activeIndex); // 'MYINDEX'
console.log($('.UserName').text()); // 正常打印
},
methods:{
ChangeName(){
if(!this.toggle){
this.UserName = '***';
}else{
this.UserName = '@UserName'; // 前后端可互通了,完美
}
this.toggle = !this.toggle;
}
}
}
mixinArray.push(subApp);
</script>
改造完成:
优点:既对其他页面没影响,又可以愉快的使用vue开发(新的页面)。
缺点:只能使用cdn模式安装。
后期也可以把其他组件作为混入对象。
兼容IE的话,请加入Babel和Polyfill。
致敬经典,Razor框架很强!❤
如果对你有所帮助,请随手点个赞,Coding不易~❤
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。