.net core + vue开发单页应用(二)

来源:互联网 发布:万能电视遥控器软件 编辑:程序博客网 时间:2024/06/05 06:46

上一篇中已将完成了基础结构的搭建,这一篇将开始正式开发。页面直接使用了一位小伙伴的源码,可以在https://github.com/taylorchen709/vue-admin下载

修改入口main.js

在入口函数中添加对element-ui,vue-router,vuex,vue-source等组件的引用

  1. import Vue from 'vue'
  2. import App from './App'
  3. import ElementUI from 'element-ui'
  4. import 'element-ui/lib/theme-default/index.css'
  5. import VueRouter from 'vue-router'
  6. import store from './vuex/store'
  7. import Vuex from 'vuex'
  8. import VueSource from 'vue-resource'
  9. import routes from './routes'
  10. import 'font-awesome/css/font-awesome.min.css'
  11. Vue.use(ElementUI)
  12. Vue.use(VueRouter)
  13. Vue.use(Vuex)
  14. Vue.use(VueSource)
  15. //创建路由实例
  16. const router = new VueRouter({
  17. routes
  18. })
  19. router.beforeEach((to, from, next) => {
  20. //这里进行了简单的登录验证
  21. //访问login时直接清除user
  22. if (to.path == '/login') {
  23. sessionStorage.removeItem('user');
  24. }
  25. let user = JSON.parse(sessionStorage.getItem('user'));
  26. if (!user && to.path != '/login') {
  27. next({ path: '/login' })
  28. } else {
  29. next()
  30. }
  31. })
  32. new Vue({
  33. router,
  34. store,
  35. render: h => h(App)
  36. }).$mount('#app')

修改App.vue

  1. <template>
  2. <div id="app">
  3. <transition name="fade"
  4. mode="out-in">
  5. <router-view></router-view>
  6. </transition>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. name: 'app',
  12. components: {
  13. }
  14. }
  15. </script>

增加viewes文件夹,并增加模块视图

login.vue

  1. <template>
  2. <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" label-position="left" label-width="0px" class="demo-ruleForm login-container">
  3. <h3 class="title">系统登录</h3>
  4. <el-form-item prop="account">
  5. <el-input type="text" v-model="ruleForm2.account" auto-complete="off" placeholder="账号"></el-input>
  6. </el-form-item>
  7. <el-form-item prop="checkPass">
  8. <el-input type="password" v-model="ruleForm2.checkPass" auto-complete="off" placeholder="密码"></el-input>
  9. </el-form-item>
  10. <el-checkbox v-model="checked" checked class="remember">记住密码</el-checkbox>
  11. <el-form-item style="width:100%;">
  12. <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit2" :loading="logining">登录</el-button>
  13. </el-form-item>
  14. </el-form>
  15. </template>
  16. <script>
  17. export default {
  18. data() {
  19. return {
  20. logining: false,
  21. ruleForm2: {
  22. account: 'admin',
  23. checkPass: '123456'
  24. },
  25. rules2: {
  26. account: [
  27. { required: true, message: '请输入账号', trigger: 'blur' },
  28. //{ validator: validaePass }
  29. ],
  30. checkPass: [
  31. { required: true, message: '请输入密码', trigger: 'blur' },
  32. //{ validator: validaePass2 }
  33. ]
  34. },
  35. checked: true
  36. };
  37. },
  38. methods: {
  39. handleReset2() {
  40. this.$refs.ruleForm2.resetFields();
  41. },
  42. handleSubmit2(ev) {
  43. var _this = this;
  44. this.$refs.ruleForm2.validate((valid) => {
  45. if (valid) {
  46. this.logining = true;
  47. //NProgress.start();
  48. var loginParams = { username: this.ruleForm2.account, password: this.ruleForm2.checkPass };
  49. if (loginParams.username != 'admin') {
  50. this.$message({
  51. message: '用户不存在',
  52. type: 'error'
  53. });
  54. this.logining = false;
  55. return false;
  56. }
  57. if (loginParams.password != '123456') {
  58. this.$message({
  59. message: '密码不正确',
  60. type: 'error'
  61. });
  62. this.logining = false;
  63. return;
  64. }
  65. let user = {
  66. id: 1,
  67. username: 'admin',
  68. password: '123456',
  69. avatar: 'resources/img/user.png',
  70. name: '管理员'
  71. }
  72. sessionStorage.setItem('user', JSON.stringify(user));
  73. this.$router.push({ path: '/' });
  74. } else {
  75. return false;
  76. }
  77. });
  78. }
  79. }
  80. }
  81. </script>
  82. <style scoped>
  83. .login-container {
  84. /*box-shadow: 0 0px 8px 0 rgba(0, 0, 0, 0.06), 0 1px 0px 0 rgba(0, 0, 0, 0.02);*/
  85. -webkit-border-radius: 5px;
  86. border-radius: 5px;
  87. -moz-border-radius: 5px;
  88. background-clip: padding-box;
  89. margin: 180px auto;
  90. width: 350px;
  91. padding: 35px 35px 15px 35px;
  92. background: #fff;
  93. border: 1px solid #eaeaea;
  94. box-shadow: 0 0 25px #cac6c6;
  95. }
  96. .title {
  97. margin: 0px auto 40px auto;
  98. text-align: center;
  99. color: #505458;
  100. }
  101. .remember {
  102. margin: 0px 0px 35px 0px;
  103. }
  104. </style>

home.vue

  1. <template>
  2. <el-row class="container">
  3. <el-col :span="24" class="header">
  4. <el-col :span="10" :class="collapsed?'logo-collapse-width logo-collapsed':'logo-width logo'">
  5. {{collapsed?'':sysName}}
  6. <!--<img :src="logo" v-show="collapsed" />-->
  7. </el-col>
  8. <el-col :span="10">
  9. <div class="tools" @click.prevent="collapse">
  10. <i class="fa fa-align-justify"></i>
  11. </div>
  12. </el-col>
  13. <el-col :span="4" class="userinfo">
  14. <el-dropdown trigger="hover">
  15. <span class="el-dropdown-link userinfo-inner"><img :src="this.sysUserAvatar" /> {{sysUserName}}</span>
  16. <el-dropdown-menu slot="dropdown">
  17. <el-dropdown-item>我的消息</el-dropdown-item>
  18. <el-dropdown-item>设置</el-dropdown-item>
  19. <el-dropdown-item divided @click.native="logout">退出登录</el-dropdown-item>
  20. </el-dropdown-menu>
  21. </el-dropdown>
  22. </el-col>
  23. </el-col>
  24. <el-col :span="24" class="main">
  25. <aside :class="collapsed?'menu-collapsed':'menu-expanded'">
  26. <!--导航菜单-->
  27. <el-menu :default-active="$route.path" class="el-menu-vertical-demo" @open="handleopen" @close="handleclose" @select="handleselect"
  28. unique-opened router v-show="!collapsed">
  29. <template v-for="(item,index) in $router.options.routes" v-if="!item.hidden">
  30. <el-submenu :index="index+''" v-if="!item.leaf">
  31. <template slot="title">
  32. <i :class="item.iconCls"></i>{{item.name}}
  33. </template>
  34. <el-menu-item v-for="child in item.children" :index="child.path" :key="child.path" v-if="!child.hidden">{{child.name}}</el-menu-item>
  35. </el-submenu>
  36. <el-menu-item v-if="item.leaf&&item.children.length>0" :index="item.children[0].path"><i :class="item.iconCls"></i>{{item.children[0].name}}</el-menu-item>
  37. </template>
  38. </el-menu>
  39. <!--导航菜单-折叠后-->
  40. <ul class="el-menu el-menu-vertical-demo collapsed" v-show="collapsed" ref="menuCollapsed">
  41. <li v-for="(item,index) in $router.options.routes" v-if="!item.hidden" class="el-submenu item">
  42. <template v-if="!item.leaf">
  43. <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"><i :class="item.iconCls"></i></div>
  44. <ul class="el-menu submenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
  45. <li v-for="child in item.children" v-if="!child.hidden" :key="child.path" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.path)">{{child.name}}</li>
  46. </ul>
  47. </template>
  48. <template v-else>
  49. <li class="el-submenu">
  50. <div class="el-submenu__title el-menu-item" style="padding-left: 20px;height: 56px;line-height: 56px;padding: 0 20px;" :class="$route.path==item.children[0].path?'is-active':''" @click="$router.push(item.children[0].path)"><i :class="item.iconCls"></i></div>
  51. </li>
  52. </template>
  53. </li>
  54. </ul>
  55. </aside>
  56. <section class="content-container">
  57. <div class="grid-content bg-purple-light">
  58. <el-col :span="24" class="breadcrumb-container">
  59. <!--<strong class="title">{{$route.name}}</strong>-->
  60. <el-breadcrumb separator="/" class="breadcrumb-inner">
  61. <el-breadcrumb-item v-for="item in $route.matched" :key="item.path">
  62. {{ item.name }}
  63. </el-breadcrumb-item>
  64. </el-breadcrumb>
  65. </el-col>
  66. <el-col :span="24" class="content-wrapper">
  67. <transition name="fade" mode="out-in">
  68. <router-view></router-view>
  69. </transition>
  70. </el-col>
  71. </div>
  72. </section>
  73. </el-col>
  74. </el-row>
  75. </template>
  76. <script>
  77. export default {
  78. data() {
  79. return {
  80. sysName:'Simple',
  81. logo:'dist/resources/img/logo.png',
  82. collapsed:false,
  83. sysUserName: '',
  84. sysUserAvatar: '',
  85. form: {
  86. name: '',
  87. region: '',
  88. date1: '',
  89. date2: '',
  90. delivery: false,
  91. type: [],
  92. resource: '',
  93. desc: ''
  94. }
  95. }
  96. },
  97. methods: {
  98. onSubmit() {
  99. console.log('submit!');
  100. },
  101. handleopen() {
  102. //console.log('handleopen');
  103. },
  104. handleclose() {
  105. //console.log('handleclose');
  106. },
  107. handleselect: function (a, b) {
  108. },
  109. //退出登录
  110. logout: function () {
  111. var _this = this;
  112. this.$confirm('确认退出吗?', '提示', {
  113. //type: 'warning'
  114. }).then(() => {
  115. sessionStorage.removeItem('user');
  116. _this.$router.push('/login');
  117. }).catch(() => {
  118. });
  119. },
  120. //折叠导航栏
  121. collapse:function(){
  122. this.collapsed=!this.collapsed;
  123. },
  124. showMenu(i,status){
  125. this.$refs.menuCollapsed.getElementsByClassName('submenu-hook-'+i)[0].style.display=status?'block':'none';
  126. }
  127. },
  128. mounted() {
  129. var user = sessionStorage.getItem('user');
  130. if (user) {
  131. user = JSON.parse(user);
  132. this.sysUserName = user.name || '';
  133. this.sysUserAvatar = user.avatar || '';
  134. }
  135. }
  136. }
  137. </script>
  138. <style scoped >
  139. .container {
  140. position: absolute;
  141. top: 0px;
  142. bottom: 0px;
  143. width: 100%;
  144. }
  145. .container .header {
  146. height: 60px;
  147. line-height: 60px;
  148. background: #20a0ff;
  149. color: #fff;
  150. }
  151. .container .header .userinfo {
  152. text-align: right;
  153. padding-right: 35px;
  154. float: right;
  155. }
  156. .container .header .userinfo .userinfo-inner {
  157. cursor: pointer;
  158. color: #fff;
  159. }
  160. .container .header .userinfo .userinfo-inner img {
  161. width: 40px;
  162. height: 40px;
  163. border-radius: 20px;
  164. margin: 10px 0px 10px 10px;
  165. float: right;
  166. }
  167. .container .header .logo {
  168. height: 60px;
  169. font-size: 22px;
  170. padding-left: 20px;
  171. padding-right: 20px;
  172. border-color: rgba(238, 241, 146, 0.3);
  173. border-right-width: 1px;
  174. border-right-style: solid;
  175. }
  176. .container .header .logo img {
  177. width: 40px;
  178. float: left;
  179. margin: 10px 10px 10px 18px;
  180. }
  181. .container .header .logo .txt {
  182. color: #fff;
  183. }
  184. .container .header .logo-collapsed {
  185. padding: 0;
  186. font-size: 22px;
  187. padding-left: 0px;
  188. padding-top: 10px;
  189. border-color: rgba(238, 241, 146, 0.3);
  190. border-right-width: 1px;
  191. border-right-style: solid;
  192. }
  193. .container .header .logo-collapsed img {
  194. width: 60px;
  195. float: left;
  196. margin: 0px;
  197. }
  198. .container .header .logo-collapsed .txt {
  199. color: #fff;
  200. }
  201. .container .header .logo-width {
  202. width: 230px;
  203. }
  204. .container .header .logo-collapse-width {
  205. width: 60px;
  206. }
  207. .container .header .tools {
  208. padding: 0px 23px;
  209. width: 14px;
  210. height: 60px;
  211. line-height: 60px;
  212. cursor: pointer;
  213. }
  214. .container .main {
  215. display: flex;
  216. position: absolute;
  217. top: 60px;
  218. bottom: 0px;
  219. overflow: hidden;
  220. }
  221. .container .main aside {
  222. flex: 0 0 230px;
  223. width: 230px;
  224. }
  225. .container .main aside .el-menu {
  226. height: 100%;
  227. }
  228. .container .main aside .collapsed {
  229. width: 60px;
  230. }
  231. .container .main aside .collapsed .item {
  232. position: relative;
  233. }
  234. .container .main aside .collapsed .submenu {
  235. position: absolute;
  236. top: 0px;
  237. left: 60px;
  238. z-index: 99999;
  239. height: auto;
  240. display: none;
  241. }
  242. .container .main .menu-collapsed {
  243. flex: 0 0 60px;
  244. width: 60px;
  245. }
  246. .container .main .menu-expanded {
  247. flex: 0 0 230px;
  248. width: 230px;
  249. }
  250. .container .main .content-container {
  251. flex: 1;
  252. overflow-y: scroll;
  253. padding: 20px;
  254. }
  255. .container .main .content-container .breadcrumb-container .title {
  256. width: 200px;
  257. float: left;
  258. color: #475669;
  259. }
  260. .container .main .content-container .breadcrumb-container .breadcrumb-inner {
  261. float: left;
  262. padding-bottom: 10px;
  263. }
  264. .container .main .content-container .content-wrapper {
  265. background-color: #fff;
  266. box-sizing: border-box;
  267. }
  268. </style>

此时编译运行可以看到下面的页面,由于还没有开发子页面,所以只显示主页和菜单: 

添加模拟的后端API

这里模拟用户管理的功能。为.net开发,具体的开发流程不在赘述。 
UserInfo.cs

  1. public class UserInfo
  2. {
  3. public string uuid { get; set; }
  4. public string login_name { get; set; }
  5. public string real_name { get; set; }
  6. public string email { get; set; }
  7. public string birthday { get; set; }
  8. public int age { get; set; }
  9. }

UserInfoRepository.cs

  1. public class UserInfoRepository
  2. {
  3. static List<UserInfo> db_users = new List<UserInfo>() {
  4. };
  5. public static IList<UserInfo> LoadAll() {
  6. return db_users;
  7. }
  8. public static string Insert(UserInfo u)
  9. {
  10. u.uuid = Guid.NewGuid().ToString();
  11. db_users.Add(u);
  12. return u.uuid;
  13. }
  14. public static string Update(UserInfo u)
  15. {
  16. db_users.Remove(db_users.Where(m => m.uuid.Equals(u.uuid)).FirstOrDefault());
  17. db_users.Add(u);
  18. return u.uuid;
  19. }
  20. public static UserInfo Get(string uuid) {
  21. return db_users.Where(m=>m.uuid.Equals(uuid)).FirstOrDefault();
  22. }
  23. public static void Delete(string uuid)
  24. {
  25. var u = db_users.Where(m => m.uuid.Equals(uuid)).FirstOrDefault();
  26. db_users.Remove(u);
  27. }
  28. }

UserController.cs

  1. [Route("api/[controller]")]
  2. public class UsersController : Controller
  3. {
  4. [HttpGet]
  5. public string Get()
  6. {
  7. return JsonConvert.SerializeObject(UserInfoRepository.LoadAll());
  8. }
  9. [HttpGet("{uuid}")]
  10. public string Get(string uuid)
  11. {
  12. return JsonConvert.SerializeObject(UserInfoRepository.Get(uuid));
  13. }
  14. [HttpGet("p/")]
  15. public string Get(string name, int page = 1, int pagesize = 20)
  16. {
  17. long count = 0;
  18. var list = UserInfoRepository.LoadAll();
  19. count = list.Count;
  20. var obj = new
  21. {
  22. total = count,
  23. list = list.Where(m => m.real_name.Equals(name)).Skip((page - 1) * pagesize).Take(pagesize)
  24. };
  25. return JsonConvert.SerializeObject(obj);
  26. }
  27. [HttpPost]
  28. public void Post([FromBody]UserInfo user)
  29. {
  30. UserInfoRepository.Insert(user);
  31. }
  32. [HttpPut]
  33. public void Put([FromBody]UserInfo user)
  34. {
  35. UserInfoRepository.Update(user);
  36. }
  37. [HttpDelete("{uuid}")]
  38. public void Delete(string uuid)
  39. {
  40. UserInfoRepository.Delete(uuid);
  41. }
  42. }

添加列表页面

添加内容包括,users.vue页面、路由以及将登录后的默认页面修改为users 
users.vue

  1. <template>
  2. <section>
  3. <!--工具条-->
  4. <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
  5. <el-form :inline="true" :model="filters">
  6. <el-form-item>
  7. <el-input v-model="filters.name" placeholder="姓名"></el-input>
  8. </el-form-item>
  9. <el-form-item>
  10. <el-button type="primary" v-on:click="search">查询</el-button>
  11. </el-form-item>
  12. <el-form-item>
  13. <el-button type="success" v-on:click="add">添加</el-button>
  14. </el-form-item>
  15. </el-form>
  16. </el-col>
  17. <!--列表-->
  18. <el-table :data="infos" highlight-current-row v-loading="listLoading" style="width: 100%;">
  19. <el-table-column type="selection" width="55">
  20. </el-table-column>
  21. <el-table-column type="index" width="60">
  22. </el-table-column>
  23. <el-table-column prop="login_name" label="登录名" sortable>
  24. </el-table-column>
  25. <el-table-column prop="real_name" label="真实姓名" sortable>
  26. </el-table-column>
  27. <el-table-column prop="email" label="邮箱" sortable>
  28. </el-table-column>
  29. <el-table-column prop="birthday" label="生日" sortable>
  30. </el-table-column>
  31. <el-table-column prop="age" label="年龄" sortable>
  32. </el-table-column>
  33. <el-table-column label="操作" width="150">
  34. <template scope="scope">
  35. <el-button type="warning" size="small" @click="edit(scope.$index, scope.row)">编辑</el-button>
  36. <el-button type="danger" size="small" @click="del(scope.$index, scope.row)">删除</el-button>
  37. </template>
  38. </el-table-column>
  39. </el-table>
  40. <el-col :span="24" class="toolbar">
  41. <el-pagination layout="prev, pager, next" @current-change="handleCurrentChange" :page-size="10" :total="total" style="float:left;"></el-pagination>
  42. </el-col>
  43. </section>
  44. </template>
  45. <script>
  46. import ElCol from "element-ui/packages/col/src/col";
  47. export default {
  48. components: {ElCol}, data(){
  49. return {
  50. filters:{
  51. name:'',
  52. },
  53. infos:[],
  54. listLoading: false,
  55. page:1,
  56. total:0
  57. };
  58. },
  59. methods:{
  60. search:function(){
  61. var _self =this;
  62. _self.listLoading=true;
  63. this.$http.get('/api/users/s',{
  64. params:{
  65. name:_self.filters.name,
  66. page:_self.page,
  67. pagesize:10
  68. }
  69. }).then((response)=>{
  70. _self.infos=response.data.list;
  71. _self.total=response.data.total;
  72. _self.listLoading=false;
  73. },(response)=>{
  74. }).catch((response)=>{});
  75. },
  76. add:function(){
  77. this.$router.push('/useradd')
  78. },
  79. edit:function(index,row){
  80. this.$router.push(
  81. { path: '/useradd', query: { uuid: row.uuid }}
  82. )
  83. },
  84. del:function(index,row){
  85. var _self =this;
  86. this.$confirm('确定删除吗?', '提示', {
  87. confirmButtonText: '确定',
  88. cancelButtonText: '取消',
  89. type: 'warning'
  90. }).then(() => {
  91. _self.$http.delete('/api/users/'+row.Uuid).then((res)=>{
  92. _self.search();
  93. _self.$message({
  94. type: 'success',
  95. message: '删除成功!'
  96. });
  97. },(res)=>{
  98. _self.$message({
  99. type: 'srror',
  100. message: '删除失败!'
  101. });
  102. }).catch();
  103. });
  104. },
  105. handleCurrentChange:function(p){
  106. this.page = p;
  107. this.search();
  108. }
  109. },
  110. mounted() {
  111. this.search();
  112. }
  113. }
  114. </script>

添加路由,在系统管理的children下添加users

  1. {
  2. path: '/',
  3. component: Home,
  4. name: '系统管理',
  5. iconCls: 'el-icon-setting',//图标样式class
  6. children: [
  7. {path: '/users', component: Users, name: '用户管理' }
  8. ]
  9. }

同样的方式增加用户添加和编辑页面,完成用户管理小模块。

总结

我们完成了在.net core下基于vue开发单页应用,这种方法实际上是利用webpack的打包功能,编译时将应用打包好,.net应用的cshtml页面再引用已打包的js文件。方案缺陷之一为:每次修改页面都需要重新build,不能同使用Node开发时实时预览页面,在实际的项目中可能并不会使用这种方式,仅供折腾。下面附上源码地址: 
https://github.com/wenjq0911/simple.git

源博客地址使用的leanote,地址在此  http://blog.leanote.com/post/wenjq0911@gmail.com

阅读全文
2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 重庆到韩国签证怎么办 重庆去韩国签证怎么办 重庆办韩国签证怎么办 故宫网上预定后怎么办 坐游轮如果晕船怎么办 听听力反应慢怎么办? 毕业证照片丢了怎么办 离线网盘有违规内容怎么办 手机不能向下拉怎么办 cad运行不了插件怎么办 ai中缺少文字怎么办 电脑被格式化了怎么办 迷你世界地图下载失败怎么办 网页上广告太多怎么办 网页打开广告太多怎么办 PS界面图标小怎么办 百度地图反应慢怎么办 汽车导航不播报怎么办 wps菜单栏隐藏了怎么办 手机导航声音小怎么办 手机导航不好用怎么办 手机导航箭头不准怎么办 手机处于离线状态怎么办 穷人让人看不起怎么办 非洲人口过多怎么办啊 鼻子上长白头怎么办 高铁查到违禁品怎么办 青岛涂料备案证怎么办 淘宝集运不能寄怎么办 防静电指数过高怎么办 手机玻璃上裂痕怎么办 车辆环保检测不合格怎么办 眼镜被擦破镜片怎么办 手机边框有刮痕怎么办 手机金属壳磨损怎么办 手机后面凹下去怎么办 pu鞋子有刮痕怎么办 漆皮皮鞋有刮痕怎么办 手机有屏幕刮痕怎么办 鞋子刮花了怎么办 手机上屏幕划痕怎么办