安装:出现登陆页无法显示:可能是php的gd2扩展未开启
FastAdmin 在 Nginx 中的配置
用的是AdminLTE后台模板require.js、less、Bower
调试错误:看runtime/log
FastAdmin 的上传代码在哪里?
一张图解析FastAdmin中的表格列表的功能
fastadmin的页面是如何生成的?
FastAdmin 如何隐藏操作栏中的“删除”按钮“?
笔记:FastAdmin 上传设置
如何修改 FastAdmin 弹窗大小?
FastAdmin 的 CRUD 不支持层级模型
fastadmin笔记,应该能解决大部分问题
一键生成数据表的crud 的记录会保存到fa_command表中
当在线命令行管理成功生成crud时生成的文件如下:如fa_tom
application/admin/contorller/Tom.php
application/admin/model/Tom.php
application/admin/validate/Tom.php
application/admin/view/tom/index.html、edit.html、add.html
application/admin/lang/zh-cn/tom.php
/public/assets/js/backend/tom.js
如果是fa_demo_tom则会生成(_分隔成目录)
application/admin/contorller/demo/Tom.php
application/admin/model/demo/Tom.php
application/admin/validate/demo/Tom.php
application/admin/view/demo/tom/index.html、edit.html、add.html
application/admin/lang/zh-cn/demo/tom.php
/public/assets/js/backend/demo/tom.js
生成菜单的记录会更新fa_auth_rule的数据 name不带方法的就是菜单显示的pidwei0是选项卡
一键生成的是层级目录的菜单,在后台展示时父级菜单会以目录名称显示,
如上面的contorller/demo/Tom.php 父菜单显示demo子菜单显示Tom ,我们必须在application/admin/lang/zh-cn.php中添加
'Demo'=>'案例','Tom'=>'案例1' 配置后菜单显示如上:
一键压缩打包(略)
在FastAdmin中如果修改了核心的JS或CSS文件,是需要重新压缩打包后在生产环境下才会生效。FastAdmin采用的是基于RequireJS
的r.js
进行JS和CSS文件的压缩打包,application/config.php
中app_debug
的值,当为true的时候是采用的无压缩的JS和CSS,当为false时采用的是压缩版的JS和CSS
多语言:
return[
'Home'=>'前台'
];
{:__('Home')}
的方式调用,而在PHP和JS中均可以使用__('Home')
的方式发起调用
如果我们需要跨模块引入其它模块的语言包,则可以在 控制器中使用loadlang方法来引入,如
$this->loadlang('模块名');
如果需要在JS中跨模块引入语言包,则需要修改Ajax.php
中的lang
这个方法
控制器
我们的控制器都必须继承自application/common/controller/Backend.php的\app\common\controller\Backend
这个基类
这个基类application/admin/library/traits/Backend.php里引入的 use \app\admin\library\traits\Backend;它有八个公共方法
index/add/edit/del/multi/recyclebin/destroy/restore/ import
查看、添加、编辑、删除、批量更新、回收站、真实删除、还原 导入
common/controller/Backend里还有好多属性:
/**
* 无需登录的方法,同时也就不需要鉴权了
* @var array
*/
protected $noNeedLogin = [];
/**
* 无需鉴权的方法,但需要登录
* @var array
*/
protected $noNeedRight = [];
/**
* 布局模板
* @var string
*/
protected $layout = 'default';
/**
* 权限控制类
* @var Auth
*/
protected $auth = null;
/**
* 快速搜索时执行查找的字段
*/
protected $searchFields = 'id';
/**
* 是否是关联查询
*/
protected $relationSearch = false;
/**
* 是否开启数据限制
* 支持auth/personal
* 表示按权限判断/仅限个人
* 默认为禁用,若启用请务必保证表中存在admin_id字段
*/
protected $dataLimit = false;
/**
* 数据限制字段
*/
protected $dataLimitField = 'admin_id';
/**
* 是否开启Validate验证
*/
protected $modelValidate = false;
/**
* 是否开启模型场景验证
*/
protected $modelSceneValidate = false;
/**
* Multi方法可批量修改的字段
*/
protected $multiFields = 'status';
方法
/**
* 加载语言文件
* @param string $name
*/
protected function loadlang($name)
{
}
/**
* 渲染配置信息
* @param mixed $name 键名或数组
* @param mixed $value 值
*/
protected function assignconfig($name, $value = '')
{
}
/**
* 生成查询所需要的条件,排序方式
* @param mixed $searchfields 快速查询的字段
* @param boolean $relationSearch 是否关联查询
* @return array
*/
protected function buildparams($searchfields = null, $relationSearch = null)
{
}
/**
* 获取数据限制的管理员ID
* 禁用数据限制时返回的是null
* @return mixed
*/
protected function getDataLimitAdminIds()
{
}
/**
* Selectpage的实现方法
*
* 当前方法只是一个比较通用的搜索匹配,请按需重载此方法来编写自己的搜索逻辑,$where按自己的需求写即可
* 这里示例了所有的参数,所以比较复杂,实现上自己实现只需简单的几行即可
*
*/
protected function selectpage()
{
}
当两张相似的表意见curd时一个没有关联模型查询一个有时的区别:
class Demo extends Backend
{
/**
* Demo模型对象
* @var \app\admin\model\Demo
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\Demo;
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
}
traits 的原idnex方法
trait Backend
{
/**
* 查看
*/
public function index()
{
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
$list = collection($list)->toArray();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
//......
}
有关联时的控制器:
class Dash extends Backend
{
/**
* Dash模型对象
* @var \app\admin\model\Dash
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\Dash;
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
/**
* 查看
*/
public function index()
{
//当前是否为关联查询
$this->relationSearch = true;
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax())
{
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField'))
{
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->with(['category'])
->where($where)
->order($sort, $order)
->fetchSql(false)
->count();
$list = $this->model
->with(['category'])
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->fetchSql(false)
->select();
//file_put_contents(__DIR__.'/../../../runtime/log/sql_'.time().'_log.txt', $total);
//file_put_contents(__DIR__.'/../../../runtime/log/sql_'.time().'_log1.txt', $list);
foreach ($list as $row) {
}
$list = collection($list)->toArray();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
}
无关联时的model
class Demo extends Model
{
// 表名
protected $name = 'demo';
// 自动写入时间戳字段
protected $autoWriteTimestamp = false;
// 定义时间戳字段名
protected $createTime = false;
protected $updateTime = false;
// 追加属性
protected $append = [
];
}
有关联时的model(多出了一个方法)
class Dash extends Model
{
// 表名
protected $name = 'dash';
// 自动写入时间戳字段
protected $autoWriteTimestamp = false;
// 定义时间戳字段名
protected $createTime = false;
protected $updateTime = false;
// 追加属性
protected $append = [
];
public function category()
{
return $this->belongsTo('Category', 'category_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
}
js
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'demo/index',
add_url: 'demo/add',
edit_url: 'demo/edit',
del_url: 'demo/del',
multi_url: 'demo/multi',
table: 'demo',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
columns: [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'name', title: __('Name')},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});
关联后的js
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'dash/index',
add_url: 'dash/add',
edit_url: 'dash/edit',
del_url: 'dash/del',
multi_url: 'dash/multi',
table: 'dash',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
columns: [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'name', title: __('Name')},
{field: 'category_id', title: __('Category_id')},
{field: 'category.id', title: __('Category.id')},
{field: 'category.pid', title: __('Category.pid')},
{field: 'category.type', title: __('Category.type')},
{field: 'category.name', title: __('Category.name')},
{field: 'category.nickname', title: __('Category.nickname')},
{field: 'category.flag', title: __('Category.flag'), operate:'FIND_IN_SET', formatter: Table.api.formatter.label},
{field: 'category.image', title: __('Category.image'), formatter: Table.api.formatter.image},
{field: 'category.keywords', title: __('Category.keywords')},
{field: 'category.description', title: __('Category.description')},
{field: 'category.diyname', title: __('Category.diyname')},
{field: 'category.createtime', title: __('Category.createtime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
{field: 'category.updatetime', title: __('Category.updatetime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
{field: 'category.weigh', title: __('Category.weigh')},
{field: 'category.status', title: __('Category.status'), formatter: Table.api.formatter.status},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});
bootstraptable详细的参数
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: '/Home/GetDepartment', //请求后台的URL(*)用于从远程站点请求数据的URL
method: 'get', //请求方式(*)
toolbar: '#toolbar', //工具栏按钮用哪个容器 一个jQuery 选择器,指明自定义的 buttons toolbar。例如:#buttons-toolbar, .buttons-toolbar 或 DOM 节点
toolbarAlign:'left' //指示如何对齐自定义工具栏。可以使用'left','right'
buttonsToolbar:'', //一个jQuery选择器,指示按钮工具栏,例如:#buttons-toolbar,.buttons-toolbar或DOM节点
buttonsAlign:'right', //指示如何对齐工具栏按钮。可以使用'left','right'。
buttonsClass:'secondary', //定义表按钮的Bootstrap类(在'btn-'之后添加)
striped: true, //是否显示行间隔色
cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: true, //是否显示分页(*) 设置为true以在表格底部显示分页工具栏默认false
sortable: true, //是否启用排序 列中也有此变量
sortName:'', //定义要排序的列 没定义默认都不排列,同sortOrder结合使用,sortOrder没写的话列默认递增(asc)
sortOrder: "asc", //定义列排序顺序,只能是'asc'或'desc'。
sortStable: false, //如果你把此属性设为了true)我们将为此行添加'_position'属性 (别看错了,是sortStable,sortable在下面)设为true,则和sort部分一样,区别是:在排序过程中,如果存在相等的元素,则原来的顺序不会改变
queryParams: oTableInit.queryParams,//传递参数(*)
sidePagination: "server", //分页方式:client客户端分页(默认),server服务端分页(*)
silentSort:true,//设置为false以便对加载的消息数据进行排序。当sidePagination选项设置为“server”时,此选项有效。
pageNumber:1, //初始化加载第一页,默认第一页
pageSize: 10, //每页的记录行数(*)
pageList: [10, 25, 50, 100], //可供选择的每页的行数(*)
search: true, //是否显示表格搜索input,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大
strictSearch: true, //启用严格搜索
showColumns: false, //是否显示所有的列 设置为true以显示列下拉列表(一个可以设置显示想要的列的下拉f按钮)
showRefresh: true, //是否显示刷新按钮 默认false
minimumCountColumns: 1, //最少允许的列数 要从列下拉列表中隐藏的最小列数
clickToSelect: true, //是否启用点击选中行
height: 500, //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度
idField:'', //表明哪个是字段是标识字段
uniqueId: "ID", //表明每一行的唯一标识字段,一般为主键列
showToggle:true, //是否显示详细视图和列表视图的切换按钮
cardView: false, //是否显示详细视图 设置为true以显示卡片视图表,例如mobile视图(卡片视图)
detailView: false, //设置为true以显示detail 视图表(细节视图)
locale:'zh-CN',
height:800, //固定表格的高度
classes:'table table-bordered table-hover',//表的类名。可以使用'table','table-bordered','table-hover','table-striped','table-dark','table-sm'和'table-borderless'。默认情况下,表格是有界的。
theadClasses:'',// 表thead的类名 如使用.thead-light或.thead-dark使theads显示为浅灰色或深灰色。
rowStyle:function(row,index){},// 行样式格式化程序函数支持类或css
rowAttributes:function(row,index){},// row属性formatter函数,支持所有自定义属性
undefinedText:'-',// 定义默认的未定义文本
sortClass:'',//已排序的td元素的类名
rememberOrder:false,//设置为true以记住每列的顺序
data:[],// 要加载的数据 [] or {}
contentType:'application/json',//请求远程数据的contentType,例如:application/x-www-form-urlencoded。
dataType:'json',//您希望服务器返回的数据类型
totalField:'total',//Key in incoming json containing 'total' data.
dataField:'rows',//名称写自己定义的每列的字段名,也就是key,通过key才能给某行的某列赋value原文:获取每行数据json内的key
onlyInfoPagination:false,//设置为true以仅显示表中显示的数据量。它需要将分页表选项即pagination设置为true
paginationLoop:true,//设置为true以启用分页连续循环模式
paginationHAlign:'right',//分页条水平方向的位置,默认right(最右),可选left
totalRows:0,//该属性主要由分页服务器传递,易于使用
paginationDetailHAlign:'left',//如果解译的话太长,举个例子,paginationDetail就是“显示第 1 到第 8 条记录,总共 15 条记录 每页显示 8 条记录”,默认left(最左),可选right
paginationVAlign:'bottom',//分页条垂直方向的位置,默认bottom(底部),可选top、both(顶部和底部均有分页条)
paginationPreText:'<',//上一页的按钮符号
paginationNextText:'>',//下一页的按钮符号
paginationSuccessivelySize:5,//分页时会有<12345...80>这种格式而5则表示显示...左边的的页数
paginationPagesBySide:1,//...右边的最大连续页数如改为2则 <1 2 3 4....79 80>
paginationUseIntermediate:false,//计算并显示中间页面以便快速访问 true 会将...替换为计算的中间页数42
searchOnEnterKey:false,// true时搜索方法将一直执行,直到按下Enter键(即按下回车键才进行搜索)
trimOnSearch:true,//默认true,自动忽略空格
searchAlign:'right',//指定搜索输入框的方向。可以使用'left','right'。
searchTimeOut:500,//设置搜索触发超时
searchText:'',//设置搜索文本框的默认搜索值
showHeader:true,//设置为false以隐藏表头
showFooter:false,//设置为true以显示摘要页脚行(固定也交 比如显示总数什么的最合适)
showPaginationSwitch:false,//设置为true以显示分页组件的切换按钮
showFullscreen:false,// 设置为true以显示全屏按钮
smartDisplay:true,//设置为true以巧妙地显示分页或卡片视图
escape:false,// 转义字符串以插入HTML,替换 &, <, >, “, `, 和 ‘字符 跳过插入HTML中的字符串,替换掉特殊字符
selectItemName:'btSelectItem',// 设置radio 或者 checkbox的字段名称
clickToSelect:false,//设置为true时 在点击列时可以选择checkbox或radio
singleSelect:false,// 默认false,设为true则允许复选框仅选择一行(不能多选了?)
checkboxHeader:true,//设置为false以隐藏标题行中的check-all复选框 即隐藏全选框
maintainSelected:false,// true时点击分页按钮或搜索按钮时,记住checkbox的选择项 设为true则保持被选的那一行的状态
icons:{//定义工具栏,分页和详细信息视图中使用的图标
paginationSwitchDown: 'fa-caret-square-down',
paginationSwitchUp: 'fa-caret-square-up',
refresh: 'fa-sync',
toggleOff: 'fa-toggle-off',
toggleOn: 'fa-toggle-on',
columns: 'fa-th-list',
detailOpen: 'fa-plus',
detailClose: 'fa-minus',
fullscreen: 'fa-arrows-alt'
},
iconSize:'undefined',// 定义icon图表的尺寸大小html对应为data-icon-undefined (默认btn)、data-icon-lg 大按钮的尺寸(btn-lg)...; 这里的值依次为undefined => btnxs => btn-xssm => btn-smlg => btn-lg
iconsPrefix:'fa',//定义图标集名称(FontAwesome的'glyphicon'或'fa')。默认情况下,'fa'用于Bootstrap v4
queryParamsType:'limit',//设置'limit'以使用RESTFul类型发送查询参数。
ajaxOptions:{},//提交ajax请求的其他选项。值列表:jQuery.ajax。
customSort:function(sortName,sortOrder,data){},//自定义排序功能(用来代替自带的排序功能),需要两个参数(可以参考前面):
ajax:function(){},// 一种替换ajax调用的方法。应该实现与jQuery ajax方法相同的API
queryParams: function(params) { // 请求远程数据时,您可以通过修改queryParams来发送其他参数
return params
},
responseHandler:function(res) { //在加载远程数据之前,处理响应数据格式,参数对象包含
return res
},
customSearch:function(data,text){// 执行自定义搜索功能替换内置搜索功能,需要两个参数
return data.filter(function (row) {return row.field.indexOf(text) > -1})
},
footerStyle:function(column){// 页脚样式格式化程序函数,只需一个参数 m默认{}
return {
css: { 'font-weight': 'normal' },
classes: 'my-class'
}
},
detailFormatter:function(index,row,element){//前提:detailView设为true,启用了显示detail view。- 用于格式化细节视图- 返回一个字符串,通过第三个参数element直接添加到细节视图的cell(某一格)中,其中,element为目标cell的jQuery element
return '';
}, detailFilter:function(index,row){//当detailView设置为true时,每行启用扩展。返回true并且将启用该行以进行扩展,返回false并禁用该行的扩展。默认函数返回true以启用所有行的扩展。
return true
}, ignoreClickToSelectOn:function(element){// 包含一个参数:element: 点击的元素。返回 true 是点击事件会被忽略,返回 false 将会自动选中。该选项只有在 clickToSelect 为 true 时才生效。
return $.inArray(element.tagName, ['A', 'BUTTON']
},
columns: [
{checkbox: false},
{radio: false},
{
radio: false,//此列转成radio上面单独领出来是应为有字段显示就不需要它呀
checkbox: false,//此列转成checkbox 单独拎出来同上
field: 'operate', //设置data-field的值
title: __('Operate'),//设置data-field的值
table: table,
events: Table.api.events.operate,
formatter: Table.api.formatter.operate,//单元格格式函数 this上下文是当前列对象
formatter: function (value, row, index,field){},
titleTooltip:'列标题工具提示文本。此选项还支持标题HTML属性',
class:'定义列的类名',
rowspan:1,//指定单元格应占用的行数。
colspan:1,//指定单元格应占用的列数。
align:'center',//指定如何对齐列数据。可以使用'left','right','center'。
halign:'center',//指定如何对齐表头。可以使用'left','right','center'。
falign:'center',//指示如何对齐表格页脚。可以使用'left','right','center'。
valign:'middle',//指出如何对齐单元格数据。可以使用'top','middle','bottom'
width:'10%',//列的宽度。如果未定义,宽度将自动扩展以适合其内容。格式'100px','10%',100,如果想表格保持列自适应并且尺寸太小,则可以忽略这项(通过类等使用min / max-width)
sortable:false,//设置为true以允许列可以排序。
order:'asc',//默认排序顺序,只能是'asc'或'desc'。
visible:true,//设置为false以隐藏列项。
cardVisible:true,//设置为false以隐藏card 视图状态中的列项
switchable:true,//设置为false以禁用可切换的列项
clickToSelect:true,//设置为true时 在点击列时可以选择checkbox或radio
footerFormatter:function(data){},//当前列对象函数该函数应返回一个字符串,其中包含要在页脚单元格中显示的文本
events::{},//使用格式化函数时的单元事件监听器 四个参数event,value,row,index; html可以这么用 <th .. data-events="operateEvent">
sorter:function(a,b,rowA,rowB){},//用于进行本地排序的自定义字段排序函数(第一个字段值,第二个字段值,第一行,第二行)
sortName:'',//提供可自定义的排序名称,而不是标题中的默认排序名称或列的字段名称
cellStyle:function(value,row,index,field){},//单元格样式格式化函数 支持classs和css
searchable:true,//设置为true以搜索此列的数据。
searchFormatter:true,//设置为true以搜索使用格式化数据
escape:false,//转义字符串以插入HTML,替换 &, <, >, “, `, and ‘ 字符。
showSelectTitle:false,//设置为true以使用'radio'或'singleSelect''复选框'选项显示列的标题。
}
]
});
var operateEvents = {
/* 'click .like' 是类名?*/
'click .like': function (e, value, row, index) {}
}
模态框
require.js
require.js作为基本的js来启动所有的js data-main属性指向了一个启动脚本加载过程的文件(一般和require文件同目录)
<script src="/assets/js/require.js" data-main="/assets/js/require-backend.js?v=1551577968"></script>
然后在 data-main指向的js文件中定义模板加载选项 注意data-main里定义加载的文件是异步的哦,如果用了require.js那么就不要在之外定义对require.js里加载的文件有依赖的js
require使用分两步; 基本的require例子
1、define()定义模块(必须返回个对象)
2、调用模块 require(function(){})
//全局配置
require.config({
// 根路径设置,paths下面全部都是根据baseUrl的路径去设置
baseUrl:'./js/',//显式的定义baseUrl;不显式定义的情况下默认是和require.js同一个目录如果定义了data-main则以data-main的路径(path以/开头、以.js结尾、含有https等协议时不会使用baseUrl?)
paths:{//显式的映射哪些不是在baseUrl目录路径的文件
// 引入jQuery.js
jquery:'plugin/jquery',
// 引入bootstrap.js
bootstrap:'plugin/bootstrap',
//引入其他的js
//custom:'cunstom'
},
shim:{//为那些没有使用define()来声明依赖关系 想要实际加载指或者涉及的模块仍然需要一个常规的require、define调用,设置shim本身不会触发代码的加载
bootstrap:{
//deps定义依赖的,这里的bootstrap依赖jquery
deps:["jquery"],
exports:'该依赖没有加载成功输出这段'或者这里也可以是个函数
}
},
//map 对于给定的模块前缀,使用一个不同的模块ID来加载该模块
该特性仅适用于那些调用了define()并将其注册为匿名模块的真正AMD模块脚本。并且,请在map配置中仅使用绝对模块ID,“../some/thing”之类的相对ID不能工作。
另外在map中支持“*”,意思是“对于所有的模块加载,使用本map配置”。如果还有更细化的map配置,会优先于“*”配置
//当“some/newmodule”调用了“require('foo')”,它将获取到foo1.2.js
//而当“some/oldmodule”调用“`require('foo')”时它将获取到foo1.0.js。
//当调用其它时将获取到fool1.1.js
foo1.0.js
foo1.1.js
foo1.2.js
some/
newmodule.js
oldmodule.js
map: {
'*': {
'foo': 'foo1.1'
},
'some/oldmodule': {
'foo': 'foo1.2'
},
'some/oldmodule': {
'foo': 'foo1.0'
}
}
});
urlArgs:RequireJS获取资源时附加在URL后面的额外的query参数。作为浏览器或服务器未正确配置时的“cache bust”手段很有用。使用cache bust配置的一个示例:
urlArgs: "bust=" + (new Date()).getTime()
packages:从CommonJS包(package)中加载模块。参见从包中加载模块。
include:xx
paths:xx
shim:xx
baseUrl:xx
map:xx
waitSeconds:命名一个加载上下文。这允许require.js在同一页面上加载模块的多个版本,如果每个顶层require调用都指定了一个唯一的上下文字符串。想要正确地使用,请参考多版本支持一节
charset:xx
config:常常需要将配置信息传给一个模块。这些配置往往是application级别的信息,需要一个手段将它们向下传递给模块。在RequireJS中,基于requirejs.config()的config配置项来实现。要获取这些信息的模块可以加载特殊的依赖“module”,并调用module.config()
nodeIdCompat: 在放弃加载一个脚本之前等待的秒数。设为0禁用等待超时。默认为7秒。
context: 指定要加载的一个依赖数组。当将require设置为一个config object在加载require.js之前使用时很有用。一旦require.js被定义,这些依赖就已加载。使用deps就像调用require([]),但它在loader处理配置完毕之后就立即生效。它并不阻塞其他的require()调用,它仅是指定某些模块作为config块的一部分而异步加载的手段而已。
deps: 指定要加载的一个依赖数组。当将require设置为一个config object在加载require.js之前使用时很有用。一旦require.js被定义,这些依赖就已加载。使用deps就像调用require([]),但它在loader处理配置完毕之后就立即生效。它并不阻塞其他的require()调用,它仅是指定某些模块作为config块的一部分而异步加载的手段而已。
callback: 在deps加载完毕后执行的函数。当将require设置为一个config object在加载require.js之前使用时很有用,其作为配置的deps数组加载完毕后为require指定的函数。
enforceDefine: 如果设置为true,则当一个脚本不是通过define()定义且不具备可供检查的shim导出字串值时,就会抛出错误。参考在IE中捕获加载错误一节。
xhtml: 如果设置为true,则使用document.createElementNS()去创建script元素。
使用:
1、
require(
['jquery', 'bootstrap'],
function ($, undefined) {
}
);
2、定义模块:具有作用域来避免全局名称空间污染
简单定义:
define({
color: "black",
size: "unisize"
});
函数式定义:
define(function () {
//Do setup work here
return {
color: "black",
size: "unisize"
}
});
存在依赖的函数式定义:
模块函数以参数"cart"及"inventory"使用这两个以"./cart"及"./inventory"名称指定的模块。在这两个模块加载完毕之前,模块函数不会被调用。
严重不鼓励模块定义全局变量。遵循此处的定义模式,可以使得同一模块的不同版本并存于同一个页面上(参见 高级用法 )。另外,函参的顺序应与依赖顺序保存一致。
返回的object定义了"my/shirt"模块。这种定义模式下,"my/shirt"不作为一个全局变量而存在。
// my/shirt.js现在有一些依赖项,cart和inventory
// 假设他们与shirt.js在同一目录中的模块
define(["./cart", "./inventory"], function(cart, inventory) {
//返回一个对象来定义"my/shirt"模块。
return {
color: "blue",
size: "large",
addToCart: function() {
inventory.decrement(this);
cart.add(this);
}
}
}
);
将模块定义为一个函数
// foo/title.js中的模块定义。 它使用之前的my/cart 和my/inventory模块,
//但由于foo/title.js与"my" 模块位于不同的目录中,因此它使用模块依赖项名称中的"my" 来查找它们。
//名称的"my" 部分可以映射到任何目录,但默认情况下,它被假定相邻"foo"目录。
define(["my/cart", "my/inventory"],
function(cart, inventory) {
//返回一个函数用来定义"foo/title".
//它获取或者设置 window title.
return function(title) {
return title ? (window.title = title) :
inventory.storeName + ' ' + cart.name;
}
}
);
定义一个命名模块
这些常由优化工具生成。你也可以自己显式指定模块名称,但这使模块更不具备移植性——就是说若你将文件移动到其他目录下,你就得重命名。一般最好避免对模块硬编码,而是交给优化工具去生成。优化工具需要生成模块名以将多个模块打成一个包,加快到浏览器的载人速度。
//明确地定义 "foo/title"模块:
define("foo/title",
["my/cart", "my/inventory"],
function(cart, inventory) {
//Define foo/title object in here.
}
);
当定义的模块依赖太多的模块时
如:
//如:
define(
['dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6', 'dep7', 'dep8'],
function(dep1, dep2, dep3, dep4, dep5, dep6, dep7, dep8){
...
}
);
//可以简化成这样
define(
function (require) {
var dep1 = require('dep1'),
dep2 = require('dep2'),
dep3 = require('dep3'),
dep4 = require('dep4'),
dep5 = require('dep5'),
dep6 = require('dep6'),
dep7 = require('dep7'),
dep8 = require('dep8');
...
}
});
注意:
一个文件一个模块
为了能在define()内部使用require的调用可以将require作一个依赖注入到模块中
生成与相对于模块的url
实例:
文件:
<script src="./require.js" data-main="main.js" type="text/javascript" defer async="true"></script>
全局配置文件main.js:
/*全局配置*/
require.config({
baseUrl:'./',
paths:{
layer:"plugin/layer",
jquery:["https://cdn.bootcss.com/jquery/3.3.1/jquery","plugin/jquery"],//可配置多个地址第一个加载不上加载第二个
bootstrap:"https://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min",
custom1:"js/custom1.0",
custom2:"js/custom1.2",//custom1.2.js
math:"js/math",//math.js
datatable:"datatable",//和baseUrl同一文件下无需在这指定都行(可省略)
},
shim:{
'datatable':{//这个键名为要是载入的目标文件的文件名,不能随便命名。
exports: '_' //exports的值为datatable.js提供的 对外接口的名称??不理解 在其他模块require引入时可以引用它
},
'datatables':{
'init':function(){
return{
sayHi: datatable,//键可以随便取名(定义数据的键),值必须和datatables.js里的变量名一致
sayHello: datatableDemo,
sayname: name,
sayLike: like,
}
},
'deps':['jquery','bootstrap'],//设置的依赖只datatable在jquery和bootstrap加载完毕后才会加载
//如果木有init这些参数我们可以简化依赖设置 例如 'datatables':['jquery','bootstrap']
//z注意bootstrap是依赖jqury的所以下面必须填上'bootstrap':['jquery'],
},
'layui':{
},
'bootstrap':['jquery'],
}
});
require(['math'], function (math){
//math:为math.js return回来的数据 {add: ƒ, mathAdd: ƒ, controller: {…}}
console.log(math.add('1 ',1));
console.log(math.controller);
});
模块文件math.js
//不依赖其他模块
//define(function (){
//define([],function (){
//依赖其他模块则第一个参数为数组值为依赖的模块(这里依赖jquey和layui还有datatable),
//jqury和layui在main.js显式指定了位置,datatable.js没有在paths里没有指定那么他的路径会默认在baseUrl
define(['jquery','layer','datatable','datatables'],function ($,layer,_,tables){
var mathAdd = function (x,y){
console.log(datatable);//这里得到datatable是undefined,非规范化的模块我们需要定义在shim中
console.log(_);//??
console.log(tables);
return parseInt($.trim(x))+parseInt($.trim(y));
};
var updateData=function(){
return '需要的代码';
};
var controller={
sex:'男',
params:{
id:'1',
name:'tom',
phone:13132613871
},
index:function(){
},
add:updateData,
eidt:function(){
}
};
return {
add: mathAdd,
mathAdd: mathAdd,
controller:controller
};
});
非规范化模块
datatable。js
var datatable={
showRow:function(index){
return idnex;
}
};
datatable。js
/*非规范的模块有许多变量对象等情况*/
var datatable={
showRow:function(index){
return idnex;
}
};
function datatableDemo(){
return 'demo';
}
var name='tom';
var like=['sing','jump','drink'];
生成的模板 两表字段 id、name、category_id(关联的多的字段)
add.html
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button><!--确定-->
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button><!--重置-->
</div>
</div>
</form>
index:
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('demo/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('demo/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('demo/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
<a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('demo/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>
<div class="dropdown btn-group {:$auth->check('demo/multi')?'':'hide'}">
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
</ul>
</div>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('demo/edit')}"
data-operate-del="{:$auth->check('demo/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
edit.html
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name}">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
关联后的模板
add
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-category_id" data-rule="required" data-source="category/selectpage" data-params='{"custom[type]":"dash"}' class="form-control selectpage" name="row[category_id]" type="text" value="">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
index:
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('dash/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('dash/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('dash/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
<a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('dash/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>
<div class="dropdown btn-group {:$auth->check('dash/multi')?'':'hide'}">
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
</ul>
</div>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('dash/edit')}"
data-operate-del="{:$auth->check('dash/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
{:$auth->check('dash/add')?'':'hide'} 检查权限 无权限加hide类隐藏
edit.html
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-category_id" data-rule="required" data-source="category/selectpage" data-params='{"custom[type]":"dash"}' class="form-control selectpage" name="row[category_id]" type="text" value="{$row.category_id}">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
新增输出下拉列表的数据:
在_initialize方法里分配查出来的管理组变量给模板
edit模板
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'', 'data-rule'=>'required'])}
</div>
</div>
模板的函数解析出来为:
echo build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'', 'data-rule'=>'required']);
调用该函数生成一个下拉列表的html(第一个参数是name值,第二个参数是数组或者,分隔的字符串)
<select class="form-control selectpicker" multiple="" name="group[]" tabindex="-98">
<option value="1"> 超级管理组</option>
<option value="2"> ├ 二级管理组</option>
<option value="3"> │ ├ 三级管理组</option>
<option value="5"> │ └ 三级管理组2</option>
<option value="4"> └ 二级管理组2</option>
</select>
common.php
if (!function_exists('build_select')) {
/**
* 生成下拉列表
* @param string $name
* @param mixed $options
* @param mixed $selected
* @param mixed $attr
* @return string
*/
function build_select($name, $options, $selected = [], $attr = [])
{
$options = is_array($options) ? $options : explode(',', $options);
$selected = is_array($selected) ? $selected : explode(',', $selected);
return Form::select($name, $options, $selected, $attr);
}
}
来源:oschina
链接:https://my.oschina.net/u/4418661/blog/3637787