[TOC] ## 静态文件引用 系统全局给大家准备了2个变量: ``` $root // 访问到public的相对根域名 比如:/ /npadmin/public/ $absroot // 访问到public的绝对根域名 比如:http://www.npadmin.com/ http://127.0.0.1/npadmin/public/ ``` 引入所有public目录里面的静态文件都可以类型这样访问到它们了: ``` <img src="{$root}static/images/xx.png"> <link type="text/css" rel="stylesheet" href="{$root}static/cms/css/index.css"/> <script src="{$absroot}static/js/common.js"></script> ``` 所有的静态文件只需要自行设置好public目录后面的路径即可。 ## 模板变量和模板渲染 ``` $this->assign('变量名', 值) // 控制中传递变量到页面 用法同TP6 View::assign return $this->fetch();// 默认模板是 当前控制器小写+下划线/当前方法小写形式.html 用法同TP6 View::fetch return $this->fetch('xx');// 自定义模板名 ``` 当然你也可以直接按TP6的文档来... ## 控制器添加css文件 控制器中可以调用`addCss`来指定当前请求需要的css文件路径: ~~~ // 单条引入: $this->addCss('/pear/admin/css/other/login.css'); ~~~ ~~~ // 批量引入: $this->addCss([ '/layui/css/layui', '/pear/component/pear/css/pear.css', '/pear/admin/css/loader.css', '/pear/admin/css/admin.css', 'np.css', 'admin/global', 'admin/common' ]); ~~~ 已添加的css文件可以使用控制器方法`removeCss`(和addCss路径字符串,前后写法要一致才能准确删除)方法来删除。 一个控制器方法(操作)对应一个模板页面: 仅当前页面需要的css文件就在当前方法中引入; 当前控制器的每个页面都有一个相同的css文件,可以在当前控制器的初始化方法中引入; 如果是当前应用的每个页面都需要的css文件,可以在当前应用的核心控制器的初始化方法中引入(比如:admin应用都需要的css文件,系统就在`app\common\controller\Admin::initialize`中引入的)。 说明: 1、所有的静态文件都应该在`项目/public/static`下,所以只需定义static以后的路径即可 2、css文件默认放置到`项目/public/static/css`目录中,所以`np.css`定义的css文件其实找的是`项目/public/static/css/np.css` 3、如果没有在css目录下的文件,就必须以`/`开头直接定义static以后的全部路径 4、`.css`后缀名可写可不写,如果没有后缀自动补齐 5、css文件都引入到head标签中 ## 控制器添加js文件 控制器中可以调用`addJs`来指定当前请求需要的js文件路径: ~~~ // 单条引入 // $this->addJs('jquery-3.4.1.min');// 这样就body内容结尾引入 $this->addJs('jquery-3.4.1.min', false);// 这样就head中引入 ~~~ ~~~ // 批量引入 $this->addJs([ '/layui/layui.js', '/pear/component/pear/pear.js', '/sortable/Sortable.min.js', 'np.js', 'admin/admin.js', 'admin/common' ]); ~~~ 已添加的css文件可以使用控制器方法`removeJs`(和addJs路径字符串,前后写法要一致才能准确删除)方法来删除。 一个控制器方法(操作)对应一个模板页面: 仅当前页面需要的js文件就在当前方法中引入; 当前控制器的每个页面都有一个相同的js文件,可以在当前控制器的初始化方法中引入; 如果是当前应用的每个页面都需要的js文件,可以在当前应用的核心控制器的初始化方法中引入(比如:admin应用都需要的js文件,系统就在`app\common\controller\Admin::initialize`中引入的)。 说明: 1、所有的静态文件都应该在`项目/public/static`下,所以只需定义static以后的路径即可 2、js文件默认放置到`项目/public/static/js`目录中,所以`'jquery-3.4.1.min`定义的js文件其实找的是`项目/public/static/js/jquery-3.4.1.min.js` 3、如果没有在js目录下的文件,就必须以`/`开头直接定义static以后的全部路径 4、`.js`后缀名可写可不写,如果没有后缀自动补齐 5、JS文件默认在body内容结尾中引入,如果需要在head中引入,第二个参数设置为false。 ## 控制器传递js数据到页面 我们知道控制中通过assign传递数据到模板中,模板中的直接写JS代码是可以使用这些变量值得。但是独立的JS文件中不可以使用assign的值(独立JS文件没有经过模板引擎,所以不会被编译)。系统也给大家准备了一种方案,方便你在独立JS文件中动态的获取控制器中处理的值。 假如控制中传递了一个mya的变量,值为'aaaa': ``` // 假如控制器中传递变量 $this->assign('mya', 'aaaa'); // 模板view目录下的xx.hmtl模板文件中: var a = '{$mya}';// 最终传输到浏览器的结果已经是 var a = 'aaaa'; // 单独的js文件中,肯定就不能不行了...... ``` 因此:JS中需要的数据,我们在控制器中利用`assignJsData`方法传出: ~~~ $this->assignJsData('变量名', 值); $this->assignJsData('root', $this->request->realRoot()); ~~~ 然后,在任意的JS代码中,就可以通过`globalJsData.变量名`来获取到对应的数据了。 ``` <script> var globalJsData = {"root":"\/","absroot":"http:\/\/www.npadmin.com\/","approot":"\/run"}; </script> ``` 系统默认已经给你在JS准备好的值有: `globalJsData.root` : 访问到public的相对根域名 可用于JS中进行路径、静态文件路径的拼接等 `globalJsData.absroot`:访问到public的绝对根域名 `globalJsData.approot`:访问到当前应用的根域名 可用于JS中进行请求路径的拼接等 举一个例子:假如我们在后台应用中,现在需要利用aJax发送一个请求(比如aritcle的delete方法模拟文件删除请求) ``` $.get('/run/article/delete', {"id":5}) // 不推荐这样,虽然这个地址默认是正常的,但是我们知道访问当然应用的根域名是可以在`congig/app.php`配件文件中修改的(`app_map`、`domain_bind`配置都可以改变当前应用的访问方式),如果一改,你这个请求不就挂了吗? // JS文件中,这样写才可以保证随便你配置怎么变,这个请求路径都是正确的: $.get(globalJsData.approot + '/article/delete', {"id":5}) // globalJsData.approot + '/控制器名/方法名', // globalJsData.approot + '/二级目录.控制器名/方法名', // 当然如果js代码是在模板中,你也可以直接用url函数 $.get('{:url('article/delete')}', {"id":5}) ``` **注意:如果你的模板中,没有做对应数据的输出,上面讲的css文件、js文件、js数据这些功能肯定也是不好使的。可参考下文** ## 推荐的主模板 ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{if !empty($meta.title)}{:implode(' - ', $meta.title)}{/if}</title> <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport"/> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/> <meta name="renderer" content="webkit"/> <meta name="HandheldFriendly" content="true"/> <meta name="format-detection" content="telephone=no, email=no"/> <meta name="keywords" content="{:implode(',', $meta.keywords)}"/> <meta name="description" content="{:implode(',', $meta.description)}"/> {:create_css_link($css, true)} <script> var globalJsData = {$globalJsData | raw}; </script> {:create_js_link($js, true)} {block name="headscript"}{/block} </head> <body class="{if empty($is_index)}pear-container {else}layui-layout-body pear-admin {/if}"> {block name="hearder"}{/block} {block name="content"}{/block} {block name="footer"}{/block} {:create_js_link($deferJs, true)} {block name="script"}{/block} </body> </html> ~~~ 当然并不是后台控制器封装了addCSS、addJs、设置meta等方法,其他应用(比如你自己开发的应用)就可以自动有文件引入和动态渲染了,肯定还是需要模板中进行配合。addCSS、addJs他们的封装代码本身很简单,仅仅是收集数据。真正的输出和渲染,还是在模板文件中获取到对应数据进行输出渲染: ``` <title>{if !empty($meta.title)}{:implode(' - ', $meta.title)}{/if}</title> 网页标题输出 <meta name="keywords" content="{:implode(',', $meta.keywords)}"/> 网站关键词输出 <meta name="description" content="{:implode(',', $meta.description)}"/> 网站描述输出 ``` `create_css_link`:输出引入css的link标签 `create_js_link`:输出引入js的script标签 输出所有控制器传递到js中的数据: ``` <script> var globalJsData = {$globalJsData | raw}; </script> ``` 这个模板只是给你一个大致的参考,你可以自由发挥......