# 1、初步写一个渲染公共模版的方法
# ① 简单过渡
app/extend/context.js代码//渲染公共模版 async renderTemplate(params = {}) { //await this.render('admin/manager/index.html', params); await this.render('admin/common/template.html', params); },
/app/controller/admin/manager.js//创建管理员列表页面 async index(){ const { ctx,app } = this; //分页:可以提炼成一个公共方法page(模型名称,where条件,其他参数options) let data = await ctx.page('Manager'); // await ctx.render('admin/manager/index.html',{ // data // }); await ctx.renderTemplate({ title: '管理员列表', data }); }
/app/view/admin/layout/main_app.html主布局栏目名称<div class="page-header"> <div class="row align-items-center"> <div class="col"> <h3 class="page-title">{{title}}</h3> <ul class="breadcrumb"> <li class="breadcrumb-item"><a href="/admin">后台首页</a></li> <li class="breadcrumb-item active">{{title}}</li> </ul> </div> </div> </div>
# ② 新建公共模版
新建
app/view/admin/common/template.html模版引擎语法if:https://nunjucks.bootcss.com/templating.html#if# 1. 自定义表格上面的按钮和表格头部
/app/controller/admin/manager.js//创建管理员列表页面 async index(){ const { ctx,app } = this; //分页:可以提炼成一个公共方法page(模型名称,where条件,其他参数options) let data = await ctx.page('Manager'); await ctx.renderTemplate({ title: '管理员列表', //现在网页title,面包屑导航title,页面标题 data, tempType:'table', //模板类型:table表格模板 ,form表单模板 table:{ //表格上方按钮,没有不要填buttons buttons: [ { url: '/admin/manager/create',//新增路径 desc: '新增管理员',//新增 //按钮名称 // icon: 'fa fa-plus fa-lg',//按钮图标 } ], //表头 columns: [ { title: 'ID', key:'id', }, { title: '管理员账号', key:'username', }, { title: '创建时间', key:'create_time', }, ], } }); }
app/view/admin/common/template.html公共模版{# 申明继承一下主布局 #} {% extends "admin/layout/main_app.html" %} {% block title %} {{title}} {% endblock %} {# 对某个区块进行重新编写代码 #} {% block main %} {# {{ data }} #} {# {% for item in data %} {{ item.username }} <br/> {% endfor %} #} <div class="card card-table"> {# 表格上面按钮 #} {% if table.buttons %} <div class="card-header"> {% for item in table.buttons %} <a href="{{item.url}}" class="btn btn-outline-primary">{{item.desc}}</a> {% endfor %} </div> {% endif %} <div class="card-body"> <div class="table-responsive"> {% if table %} <table class="table table-hover table-center mb-0"> {# 表头 #} <thead> <tr> {# <th>管理员账号</th> <th width="120">创建时间</th> <th class="text-center" width="100">操作</th> #} {% for item in table.columns %} <th>{{item.title}}</th> {% endfor %} </tr> </thead> <tbody> {% for item in data %} <tr> {% for item2 in table.columns %} <td>{{ item[item2.key] }}</td> {% endfor %} {# <td> <h2 class="table-avatar"> <a href="#" class="avatar avatar-sm mr-2"> <img class="avatar-img rounded-circle" src="{{item.avatar}}" alt="User Image"></a> <a href="#">{{ item.username }} <span>管理员</span></a> </h2> </td> <td>{{ item.create_time }}</td> <td class="text-right"> <div class="actions"> <a href="#" class="btn btn-sm bg-success-light mr-2"> <i class="fe fe-pencil"></i> 修改 </a> <a href="#" class="btn btn-sm bg-danger-light"> <i class="fe fe-trash"></i> 删除 </a> </div> </td> #} </tr> {% endfor %} </tbody> </table> {% endif %} </div> </div> <div class="card-footer d-flex justify-content-center"> {# 安全起见,egg.js官方默认将代码过滤成字符串,这里我们采用过滤器进行解码 #} {{ ctx.locals.pageHtml | safe }} </div> </div> {% endblock %}# 2. 自定义表格头部的操作【修改、删除】部分
/app/controller/admin/manager.js//创建管理员列表页面 async index() { const { ctx, app } = this; //分页:可以提炼成一个公共方法page(模型名称,where条件,其他参数options) let data = await ctx.page('Manager'); //渲染公共模版 await ctx.renderTemplate({ title: '管理员列表',//现在网页title,面包屑导航title,页面标题 data, tempType: 'table', //模板类型:table表格模板 ,form表单模板 table: { //表格上方按钮,没有不要填buttons buttons: [ { url: '/admin/manager/create',//新增路径 desc: '新增管理员',//新增 //按钮名称 // icon: 'fa fa-plus fa-lg',//按钮图标 } ], //表头 columns:[ { title:'管理员账号', key:'username', class: 'text-left', }, { title:'创建时间', key:'create_time', class: 'text-center', //可选 width: 220, //可选 }, { title:'操作', class: 'text-right', action: { // 修改 edit: function (id) { return `/admin/manager/edit/${id}` }, // 删除 delete: function (id) { return `/admin/manager/delete/${id}` }, } }, ], }, }); }
app/view/admin/common/template.html公共模版... <thead> {# 表头 #} <tr> {# <th>管理员账号</th> <th width="120">创建时间</th> <th class="text-center" width="100">操作</th> #} {% for item in table.columns %} <th class="{{item.class}}" width="{{item.width}}">{{item.title}}</th> {% endfor %} </tr> </thead> ... <tbody> {% for item in data %} <tr> {% for item2 in table.columns %} {% if item2.key %} {# 如果存在key,说明是渲染数据 #} <td class="{{item2.class}}" width="{{item2.width}}">{{ item[item2.key] }}</td> {% elif item2.action %} {# 如果存在action 说明是操作 #} <td class="{{item2.class}}" width="{{item2.width}}"> <div class="actions"> {# 存在修改按钮 #} {% if item2.action.edit %} <a href="{{item2.action.edit(item.id)}}" class="btn btn-sm bg-success-light mr-2"> <i class="fe fe-pencil"></i> 修改 </a> {% endif %} {# 存在删除按钮 #} {% if item2.action.delete %} <a href="{{item2.action.delete(item.id)}}" class="btn btn-sm bg-danger-light"> <i class="fe fe-trash"></i> 删除 </a> {% endif %} </div> </td> {% else %} {# 其他情况 #} {% endif %} {% endfor %} </tr> {% endfor %} </tbody> ...# 3. 处理表格模版、表单模版(创建管理员表单公共模版为例)
可将表单模版,表格模版分别放在新的模版页面方便管理
/app/controller/admin/manager.js控制器//创建管理员---创建页面表单 async create() { const { ctx } = this; //await ctx.render('admin/manager/create.html'); //渲染公共模版 await ctx.renderTemplate({ title: '创建管理员',//现在网页title,面包屑导航title,页面标题 tempType: 'form', //模板类型:table表格模板 ,form表单模板 form:{ //提交地址 action:"/admin/manager/save", //字段配置 fields:[ { label:'管理员账号', type: 'text', name: 'username', placeholder: '请输入管理员账号', }, { label:'管理员密码', type: 'password', name: 'password', placeholder: '请输入管理员密码', }, { label:'管理员头像', type: 'file', name: 'avatar', } ], } }); }
app/view/admin/layout/_table.html表格模版<div class="card card-table"> {# 表格上面的按钮 #} {% if table.buttons %} <div class="card-header"> {% for item in table.buttons %} <a href="{{ item.url}}" class="btn btn-outline-primary">{{item.desc}}</a> {% endfor %} </div> {% endif %} <div class="card-body"> <div class="table-responsive"> <table class="table table-hover table-center mb-0"> <thead> {# 表头 #} <tr> {# <th>管理员账号</th> <th width="120">创建时间</th> <th class="text-center" width="100">操作</th> #} {% for item in table.columns %} <th class="{{item.class}}" width="{{item.width}}">{{item.title}}</th> {% endfor %} </tr> </thead> <tbody> {% for item in data %} <tr> {% for item2 in table.columns %} {% if item2.key %} {# 如果存在key,说明是渲染数据 #} <td class="{{item2.class}}" width="{{item2.width}}">{{ item[item2.key] }}</td> {% elif item2.action %} {# 如果存在action 说明是操作 #} <td class="{{item2.class}}" width="{{item2.width}}"> <div class="actions"> {# 存在修改按钮 #} {% if item2.action.edit %} <a href="{{item2.action.edit(item.id)}}" class="btn btn-sm bg-success-light mr-2"> <i class="fe fe-pencil"></i> 修改 </a> {% endif %} {# 存在修改删除 #} {% if item2.action.delete %} <a href="{{item2.action.delete(item.id)}}" class="btn btn-sm bg-danger-light"> <i class="fe fe-trash"></i> 删除 </a> {% endif %} </div> </td> {% else %} {# 其他情况 #} {% endif %} {% endfor %} </tr> {% endfor %} </tbody> </table> </div> </div> <div class="card-footer d-flex justify-content-center"> {# 安全起见,egg.js官方默认将代码过滤成字符串,这里我们采用过滤器进行解码 #} {{ ctx.locals.pageHtml | safe }} </div> </div>
app/view/admin/layout/_form.html表单模版<div class="card"> <div class="card-body"> {% if form %} <form action="{{form.action}}" method="post"> {% for item in form.fields %} <div class="form-group row"> <label class="col-form-label col-md-2">{{item.label}}</label> <div class="col-md-10"> <input type="{{item.type}}" class="form-control" name="{{item.name}}" placeholder="{{item.placeholder}}..."> </div> </div> {% endfor %} {# <div class="form-group row"> <label class="col-form-label col-md-2">管理员账号</label> <div class="col-md-10"> <input type="text" class="form-control" name="username" placeholder="管理员账号..."> </div> </div> <div class="form-group row"> <label class="col-form-label col-md-2">管理员密码</label> <div class="col-md-10"> <input type="password" class="form-control" name="password" placeholder="管理员密码..."> </div> </div> <div class="form-group row"> <label class="col-form-label col-md-2">管理员头像</label> <div class="col-md-10"> <input class="form-control" type="file" name="avatar"> </div> </div> #} <div class="text-right mt-3"> <button type="submit" class="btn btn-primary">提 交</button> </div> </form> {% endif %} </div> </div>
app/view/admin/common/template.html公共模版判断(这部分可以写进主模版 main_app.html){# 申明继承一下主布局 #} {% extends "admin/layout/main_app.html" %} {% block title %} {{title}} {% endblock %} {# 对某个区块进行重新编写代码 #} {% block main %} {% if tempType === 'table' %} {% include "admin/layout/_table.html" %} {% endif %} {% if tempType === 'form' %} {% include "admin/layout/_form.html" %} {% endif %} {% endblock %}
# ③ 扩展公共模版功能,如公共模版表格中的删除管理员功能,并封装一个提示消息组件
- 删除管理员方法:
/app/controller/admin/manager.js控制器//删除管理员功能 async delete(){ const { ctx, app } = this; const id = ctx.params.id; await app.model.Manager.destroy({ where:{ id:id } }); //提示 ctx.toast('删除成功','success'); //跳转 ctx.redirect('/admin/manager/index'); }
- 定义路由
app/router/admin.js//删除管理员 router.get('/admin/manager/delete/:id', controller.admin.manager.delete);
- 消息提示方法
app/extend/context.js用到的知识点: egg.js项目: Cookie 与 Session//消息提示 toast(msg,type='danger'){ this.cookies.set('toast',JSON.stringify({ msg:msg, type:type }),{ maxAge:1500, //1.5秒后失效 encrypt:true // 中文提示要加密,因此这里加密 }); }
- 消息提示的信息合并进公共模版中
app/extend/context.js//渲染公共模版 async renderTemplate(params) { //获取cookie中的消息提示内容 toast let toast = this.cookies.get('toast',{ //中文需要解密 encrypt:true }); //合并到参数中 params.toast = toast ? JSON.parse(toast) : null; return await this.render('admin/common/template.html',params); },
- 考虑到消息提示整个后台都可以用,将消息提示代码放进主布局模版
app/view/admin/layout/main_app.html... <script src="/public/assets/js/vue.2.7.0.min.js"></script> <script src="/public/assets/js/vue.component.js"></script> <body> <!-- Main Wrapper --> <div class="main-wrapper" id="vueapp"> {# 提示组件 #} <toast ref="toast"></toast> .... <!-- Custom JS --> <script src="/public/assets/js/script.js"></script> {% block js %} <script> var Vueapp = new Vue({ el: '#vueapp', }); </script> {% endblock %} <script> // 调用组件 var toast = "{{ toast.msg}}"; if(toast && Vueapp && Vueapp.$refs.toast){ Vueapp.$refs.toast.show({ msg:'{{ toast.msg }}', type:'{{ toast.type }}' }); } </script>// 自定义组件 // 消息提示组件 Vue.component('toast', { template:` <div class="alert" style="position: fixed;top: 70px;right: 0px;z-index: 10000;" v-if="toast" :class="classes"> {{ msg }} </div> `, data() { return { msg:"", toast:false, timer:null, type:"danger" } }, computed:{ classes:function(){ return 'alert-'+this.type; } }, methods: { show:function(options){ this.msg = options.msg || '提示'; this.type = options.type || 'danger'; this.toast = true; if(this.timer){ clearTimeout(this.timer); } this.timer = setTimeout(()=>{ this.hide(); this.timer = null; }, options.delay || 1500); }, hide:function(){ this.toast = false; }, } });
# ④ 扩展公共模版功能,如公共模版表格中的删除管理员功能,在删除的时候,提示确认删除弹出框组件
app/public/assets/js/vue.component.js自定义弹出框组件# bootstrap4菜鸟教程 bootstrap4菜鸟教程模态框
# bootstrap4中文文档 bootstrap4中文文档:https://bs4.vx.link/ 模态框
//弹出框组件 Vue.component('confirm', { template:` <div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalCenterTitle">{{title}}</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> {{content}} </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal" @click="hide">取消</button> <button type="button" class="btn btn-primary" @click="confirm">确定</button> </div> </div> </div> </div> `, data(){ return { title:'提示', content:'提示内容', success:null } }, methods:{ show(options){ this.title = options.title || '提示'; this.content = options.content || '提示内容'; this.success = options.success || null; $('#exampleModalCenter').modal('show'); }, hide(){ $('#exampleModalCenter').modal('hide'); }, confirm(){ if(this.success && typeof this.success === 'function'){ this.success(); } this.hide(); } } });
- 主布局模版
app/view/admin/layout/main_app.html... <script src="/public/assets/js/vue.2.7.0.min.js"></script> <script src="/public/assets/js/vue.component.js"></script> <script> var Vueapp = new Vue({ el: '#vueapp', }); </script> <body> <!-- Main Wrapper --> <div class="main-wrapper" id="vueapp"> {# 提示组件 #} <toast ref="toast"></toast> {# 弹出框模态框组件 #} <confirm ref="confirm"></confirm> .... <!-- Custom JS --> <script src="/public/assets/js/script.js"></script> {% block js %} {% endblock %} <script> // 调用组件 var toast = "{{ toast.msg}}"; if(toast && Vueapp && Vueapp.$refs.toast){ Vueapp.$refs.toast.show({ msg:'{{ toast.msg }}', type:'{{ toast.type }}' }); } //调用弹出框 // Vueapp.$refs.confirm.show({ // title:'确认删除', // content:'您确定要删除该管理员吗?', // success:function(){ // console.log('删除成功'); // } // }); </script>
- 表格模版
app/view/admin/layout/_table.html处理删除按钮{# 如果存在action 说明是操作 #} <td class="{{item2.class}}" width="{{item2.width}}"> <div class="actions"> {# 存在修改按钮 #} {% if item2.action.edit %} <a href="{{item2.action.edit(item.id)}}" class="btn btn-sm bg-success-light mr-2"> <i class="fe fe-pencil"></i> 修改 </a> {% endif %} {# 存在修改删除 #} {% if item2.action.delete %} <a class="btn btn-sm bg-danger-light" @click="del('{{item2.action.delete(item.id)}}')"> <i class="fe fe-trash"></i> 删除 </a> {% endif %} </div> </td> ... <script> Vueapp = new Vue({ el:'#vueapp', methods:{ del(url){ //调用弹出框 this.$refs.confirm.show({ title:'确认删除', content:'您确定要删除该管理员吗?', success:function(){ window.location.href=url; console.log('删除成功'); } }); } } }); </script>
# ⑤ 扩展公共模版功能,如修改管理员
# 1.先完成修改管理员界面
/app/controller/admin/manager.js控制器定义修改管理员界面方法,以及修改管理员数据功能方法//修改管理员界面 async edit(){ const { ctx, app } = this; const id = ctx.params.id; let data = await app.model.Manager.findOne({ where: { id } }); if(!data){ return await ctx.pageFail('该管理员不存在'); } // 将查询结果转成json字符串后转成json对象,删除密码 data = JSON.parse(JSON.stringify(data)); delete data.password; //console.log(data); //渲染公共模版 await ctx.renderTemplate({ id, title: '修改管理员',//现在网页title,面包屑导航title,页面标题 tempType: 'form', //模板类型:table表格模板 ,form表单模板 form:{ //提交地址 action:'/admin/manager/update/'+ id, // 字段 fields:[ { label:'管理员账号', type: 'text', name: 'username', placeholder:'请输入管理员账号', }, { label:'管理员密码', type: 'password', name: 'password', placeholder:'请输入管理员密码', }, { label:'管理员头像', type: 'file', name: 'avatar', } ], //由于是修改,则表单上面默认有值 data:data, } }); } //修改管理员功能 async update(){ }
- 定义路由
app/router/admin.js//修改管理员界面 router.get('/admin/manager/edit/:id', controller.admin.manager.edit); //修改管理员功能 router.post('/admin/manager/update/:id', controller.admin.manager.update);
- 没有数据的错误提示方法
app/extend/context.js//页面错误提示 async pageFail(data='',code=404){ return await this.render('admin/common/404.html',{ data,code }) },
- 没有数据的错误提示404页面, 新建:
app/view/admin/common/404.html<body class="error-page"> <!-- Main Wrapper --> <div class="main-wrapper"> <div class="error-box"> <h1>{{code}}</h1> <p class="h4 font-weight-normal">{{data}}</p> <a href="/admin" class="btn btn-primary">返回后台首页</a> </div> </div> <!-- /Main Wrapper --> .... </body>
- 修改管理员表单,公共模版绑定默认值
app/view/admin/layout/_form.html... <div class="col-md-10"> <input type="{{item.type}}" class="form-control" name="{{item.name}}" placeholder="{{item.placeholder}}..." value="{{form.data[item.name]}}"> </div> ...# 2.完成修改管理员数据功能,并封装成功或者失败的api接口提示方法
涉及知识点:章节2:egg.js基础-
where操作符/app/controller/admin/manager.js控制器//修改管理员数据功能 async update() { const { ctx, app } = this; // 参数验证 ctx.validate({ id: { type: 'int', required: true, }, username: { type: 'string', //参数类型 required: true, //是否必须 // defValue: '', desc: '管理员账号' //字段含义 }, password: { type: 'string', // required: true, // defValue: '', desc: '管理员密码' }, }); // 拿参数 const id = ctx.params.id; const { username, password } = ctx.request.body; // 先看一下管理员是否存在 const manager = await app.model.Manager.findOne({ where: { id } }); if (!manager) { //return ctx.pageFail('该管理员不存在', 404); return ctx.apiFail('该管理员不存在'); } //存在,由于管理员的账号具有唯一性,你不能修改账号的时候,修改成存在的账号 // if (await app.model.Manager.findOne({ // where: { // username // } // })) { // return ctx.pageFail('该管理员账号已经存在,不能修改成该管理员账号', 404); // } //也就是查询的数据id不是当前id,就是修改的当前账号除外 const Op = app.Sequelize.Op;//拿Op,固定写法 if (await app.model.Manager.findOne({ where: { username, id: { [Op.ne]: id }, } })) { //return ctx.pageFail('该管理员账号已经存在,不能修改成该管理员账号', 404); return ctx.apiFail('该管理员账号已经存在,不能修改成该管理员账号'); } // 执行修改数据 manager.username = username; if(password){ manager.password = password; } await manager.save(); // //给一个反馈 // this.ctx.status = 200; // this.ctx.body = { // msg: 'ok', // data: '修改成功' // }; ctx.apiSuccess('修改成功'); }
app/extend/context.js封装成功或者失败的api接口提示方法//api接口形式成功提示 apiSuccess(data = '', msg = 'ok', code = 200) { this.body = { msg, data }; this.status = code; }, //api接口形式失败提示 apiFail(data = '', msg = 'fail', code = 400) { this.body = { msg, data }; this.status = code; },
# 2、优化公共表单模版
# 2.1 使用Vue中的v-model对文本框进行双向数据绑定,取消value属性
我们发现提交修改数据之后,给我们反馈的是api接口提示,最好是可以给我们返回前面的消息组件的提示,本节课我们来优化一下表单提示功能
# ① 思维引入:理解vue中的数据绑定v-model
app/view/admin/layout/_form.html表单模版<div class="form-group row"> <label class="col-form-label col-md-2">管理员账号</label> <div class="col-md-10"> <input type="text" class="form-control" name="username" placeholder="管理员账号..." {/* v-model="username" */} v-model="form.username" > </div> </div> <script> Vueapp = new Vue({ el:'#vueapp', data(){ return{ {/* username:'迪丽热巴', */} form:{ username:'迪丽热巴', password:'123456', } } }, methods:{ } }); </script># ② 模版引擎渲染出data中的字段和值
{% for item in form.fields %} <div class="form-group row"> <label class="col-form-label col-md-2">{{item.label}}</label> <div class="col-md-10"> <input type="{{item.type}}" class="form-control" name="{{item.name}}" placeholder="{{item.placeholder}}..." v-model="form.{{item.name}}"> </div> </div> {% endfor %} <script> Vueapp = new Vue({ el:'#vueapp', data(){ return{ /* form:{ username:'迪丽热巴', password:'123456' } */ //需要通过模版引擎拿这些值,字段名:form.fields.name 值:默认值传递过来的 //模版引擎会最先渲染,不管你是什么代码,写完后大家可以查看源代码看到渲染后的代码 form:{ {% for item in form.fields %} {{item.name}} : "{{form.data[item.name]}}", {% endfor %} }, } }, methods:{ } }); </script># ③ 如果我们在新增表单中还希望给表单字段一个默认值
/app/controller/admin/manager.js控制器//创建管理员---创建页面表单 async create() { .... form: { //提交地址 action: "/admin/manager/save", // 字段 fields: [ { label: '管理员账号', type: 'text', name: 'username', placeholder: '请输入管理员账号', default:'默认值测试', //新增时候默认值,可选 }, ... ], } }则可以优化:
app/view/admin/layout/_form.html表单模版
模版引擎的三元表单式:模版引擎的三元表单式(If 表达式)<script> Vueapp = new Vue({ el:'#vueapp', data(){ return{ /* form:{ username:'迪丽热巴', password:'123456' } */ //需要通过模版引擎拿这些值,字段名:form.fields.name 值:默认值传递过来的 //模版引擎会最先渲染,不管你是什么代码,写完后大家可以查看源代码看到渲染后的代码 // form:{ // {% for item in form.fields %} // {{item.name}} : "{{form.data[item.name]}}", // {% endfor %} // }, //当新增表单有默认值时候 // 模版引擎的三元表达式语法: // {{ true(真的代码) if 条件 else false(假的代码)}} form:{ {% for item in form.fields %} {{item.name}} : "{{ form.data[item.name] if form.data[item.name] else item.default }}", {% endfor %} }, } }, methods:{ } }); </script>
# 2.2 完成表单提示消息功能
# ① 使用jquery的ajax来提交表单
app/view/admin/layout/_form.html表单模版<div class="text-right mt-3"> <button type="submit" class="btn btn-primary" @click.stop.prevent="submit">提 交</button> </div> <script> Vueapp = new Vue({ el:'#vueapp', data(){ return { /* form:{ username:'迪丽热巴', }, */ //需要通过模版引擎拿这些值,字段名:form.fields.name 值:默认值传递过来的 //模版引擎会最先渲染,不管你是什么代码,写完后大家可以查看源代码看到渲染后的代码 form:{ {% for item in form.fields %} {{item.name}} : "{{ form.data[item.name] if form.data[item.name] else item.default }}", {% endfor %} }, } }, methods:{ submit(){ // console.log('提交数据'); $.ajax({ type: 'POST', //这里可以换成 GET url: '{{form.action}}?_csrf={{ctx.csrf|safe}}', // contentType:'application/x-www-form-urlencoded', contentType:'application/json;chatset=UTF-8', data:JSON.stringify(this.form), success: function (response, stutas, xhr) { // console.log(response) Vueapp.$refs.toast.show({ msg:"{{'修改' if id else '新增' }}成功", type:'success', delay:1000, success:function(){ // 新增或者修改成功后,跳转到指定页面 window.location.href="{{successUrl}}"; } }); }, error:function(e){ console.log(e); Vueapp.$refs.toast.show({ msg:e.responseJSON.data, type:'danger', delay:3000 }); } }); } } }); </script># ② 提交成功之后,重新跳转到指定页面
Vue自定义组件
app/public/assets/js/vue.component.js// vue自定义组件 //消息提示组件 Vue.component('toast', { ... methods:{ show:function(options){ this.msg = options.msg || '提示'; this.type = options.type || 'danger'; this.toast = true; if(this.timer){ clearTimeout(this.timer); } this.timer = setTimeout(()=>{ this.hide(); this.timer = null; //新增执行回调函数 if(options.success && typeof options.success == 'function'){ options.success(); } },options.delay || 1500); }, hide:function(){ this.toast = false; } }, ... });在控制器
/app/controller/admin/manager.js创建管理员---创建页面表单create()和修改管理员界面edit()方法都加上成功后的跳转地址//创建管理员---创建页面表单 async create() { ... //渲染公共模版 await ctx.renderTemplate({ title: '创建管理员',//现在网页title,面包屑导航title,页面标题 tempType: 'form', //模板类型:table表格模板 ,form表单模板 form: { ... }, //新增成功之后的跳转页面 successUrl: '/admin/manager/index', }); } //修改管理员界面 async edit() { ... //渲染公共模版 await ctx.renderTemplate({ id, title: '修改管理员',//现在网页title,面包屑导航title,页面标题 tempType: 'form', //模板类型:table表格模板 ,form表单模板 form: { ... }, //修改成功之后的跳转页面 successUrl: '/admin/manager/index', }); }