由于本人不是专业的前端,也没人给我设计一个轻博客。所以我只能利用互联网上的资源。 辛亏有了Bootstrap3,我也能冒充一下前端。
> 它山之石,可以攻玉
# 前端CSS框架选择
本来还犹豫试试Amaze UI的jquery版, 但是Amaze UI 由于出来的晚,不是很完善,也没有像 <http://expo.bootcss.com/> 这样的案例展示墙,想参照自定义要费一番功夫。
![2015-06-07/5573957e27c5a](http://box.kancloud.cn/2015-06-07_5573957e27c5a.png)
然后幸运的是bootstrap 自带了一个博客案列:
![2015-06-07/55739600701b9](http://box.kancloud.cn/2015-06-07_55739600701b9.png)
![http://v3.bootcss.com/examples/blog/](http://box.kancloud.cn/2015-06-07_5573962267bee.png)
感觉上挺简洁,也支持响应式。
# js类库
- jquery 这是必须的,原生js不会,开发效率慢。jq的组件比较多,也比较熟。
- audiojs 用于音频播放
- bootstrap-table 用于自己实现移植ueditor里音乐搜索功能
- jcrop 图片裁剪库,用于生成头像
- jqnotifybar 用于做自定义提示
- tagsinput 实现发布页面的标签提示
- nprogress 用于ajax请求时的动态等待进度条
- plupload 一个html5上传组件
- smalot-bootstrap-datetimepicker 日期选择器 支持时间的选择
- uploadify swf上传插件,在OneThink和之前的项目里用烂了。
- ueditor 百度文本编辑器
- swipebox 图片展示slidebox
# web组件的安装
由于要用到这么多的组件,一个个去官网上下载太麻烦了。索性用了一下 [bower-一个Web的包管理工具](https://github.com/bower/bower)。这货可以解决包依赖问题,虽然下下来的资源可能比你需要的多,因为是将项目框架仓库整个git pull 下来。里面可能会有demo、tests和readme.md。
安装首先要有node,这个去官网下载安装就好。
然后 `npm install -g bower` 全局安装这个命令就好了。
~~~
# install dependencies listed in bower.json
$ bower install
# install a package and add it to bower.json
$ bower install <package> --save
# install specific version of a package and add it to bower.json
$ bower install <package>#<version> --save
~~~
也可以卸载某个包
`$ bower uninstall <package-name>`
具体使用方法,我就不介绍了。大家可以谷歌百度。
当然,有的时候由于项目可能被墙的原因,大家可能下载不了某个包。这时候只能靠人力了。我一般是 “红杏”翻墙访问,然后把下载地址放到115或者百度云盘里离线下载(我的迅雷会员到期了,迅雷没落后就不想充了)。
# 前端资源目录
上面的swipebox 是我自己下的,ueditor是找了一个ThinkPHP整合版,所以手动放置了。
大家可以看下我的前端目录就知道了:
![2015-06-07/55739b1c18b6a](http://box.kancloud.cn/2015-06-07_55739b1c18b6a.png)
一般我喜欢前端资源放Public里。然后 bower_components 是bower安装的目录。
* css 样式目录
* images图片库
* js 自定义js
* static 是手动安装的js组件库
html5shiv.js 和respond.js 是为了兼容性的,
think.js 是OneThink里,苗儿曾经写过 js的 兼容TP U函数的js实现。还有一个setValue 表单赋值函数。
# 代码实现
## 变量替换
前面我们找了一个 博客静态页面。
然后,我们TP就要把它套好,能正常访问。
在套之前,我们先定义下模板常量,这样方便我们在模板中使用资源路径。
忘了交代项目目录了:
![整个项目目录](http://box.kancloud.cn/2015-06-07_55739eb79621b.png)
主要是应用目录 分了 Admin后台,Api rest接口,Common 公共模块,Home 前台 。Uploads是上传目录。 test是单元测试目录。用了多入口绑定。因此除了index.php 还有 admin.php、api.php。
README.md 项目介绍文档。
在`/App/Home/Conf/config.php` 前台配置里 配置上模板解析常量
~~~
<?php
return array(
/* 模板相关配置 */
'TMPL_PARSE_STRING' => array(
'__STATIC__' => __ROOT__ . '/Public/static',
'__BOWER__'=>__ROOT__. '/Public/bower_components',
'__IMG__' => __ROOT__ . '/Public/images',
'__CSS__' => __ROOT__ . '/Public/css',
'__JS__' => __ROOT__ . '/Public/js',
),
'SHOW_PAGE_TRACE'=>true,
);
~~~
然后把 `view-source:http://v3.bootcss.com/examples/blog/` chrome里右键查看那个博客的源码 复制下来的代码 先存到/App/Home/View/Index/index.html里,然后所有 资源文件的路径替换掉。有的如
`http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js` 这种直接 粘贴地址栏里 访问在右键保存到项目目录里。
替换前:
~~~
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">
<title>Blog Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="blog.css" rel="stylesheet">
<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
<script src="../../assets/js/ie-emulation-modes-warning.js"></script>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
~~~
替换后:
~~~
<html>
<head>
<meta charset="UTF-8">
<title>Freelog - 自由的轻博客</title>
<script src="__BOWER__/jquery/dist/jquery.min.js"></script>
<script src="__BOWER__/bootstrap/dist/js/bootstrap.min.js"></script>
<link href="__BOWER__/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="__CSS__/blog.css">
<link rel="stylesheet" href="__BOWER__/jqnotifybar/css/jquery.notifyBar.css">
<script type="text/javascript" src="__BOWER__/jqnotifybar/jquery.notifyBar.js"></script>
<script type="text/javascript" src="__JS__/common.js"></script>
<script type="text/javascript">
// var url = window.location.pathname + window.location.search;
// url = url.replace(/(\/(p)\/\d+)|(&p=\d+)|(\/(id)\/\d+)|(&id=\d+)|(\/(group)\/\d+)|(&group=\d+)/, "");
var url = '__SELF__';
var no_pic = '__PUBLIC__/images/no-cover.png';
(function(){
var ThinkPHP = window.Think = {
"ROOT" : "__ROOT__", //当前网站地址
"APP" : "__APP__", //当前项目地址
"PUBLIC" : "__PUBLIC__", //项目公共目录地址
"DEEP" : "{:C('URL_PATHINFO_DEPR')}", //PATHINFO分割符
"MODEL" : ["{:C('URL_MODEL')}", "{:C('URL_CASE_INSENSITIVE')}", "{:C('URL_HTML_SUFFIX')}"],
"VAR" : ["{:C('VAR_MODULE')}", "{:C('VAR_CONTROLLER')}", "{:C('VAR_ACTION')}"]
}
})();
$(function(){
//单页高亮
$('.navbar-nav li').removeClass('active');
$('a.blog-nav-item[href="'+url+'"]').parent().addClass('active');
})
</script>
<!-- Your site ends -->
<block name="style"></block>
</head>
~~~
后面所有的静态资源路径都这么解决。
## 模板继承
前端页面其实很多页面风格一样,只是变了内容区域或者,上下左右某块区域的内容。
ThinkPHP为我们提供了模板继承这个功能,让我们将共同的部分定义成父模板的一个个块,让我们子模板继承了以后,如果不用相应的block去替换,就可以获取父模板里原有块的内容,非常方便。
所以,我将之前的模板先 全部复制了 保存到 Index/base.html里。
然后,定义了一些区块
~~~
<html>
<head>
<meta charset="UTF-8">
<title>Freelog - 自由的轻博客</title>
<script src="__BOWER__/jquery/dist/jquery.min.js"></script>
<script src="__BOWER__/bootstrap/dist/js/bootstrap.min.js"></script>
<link href="__BOWER__/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="__CSS__/blog.css">
<link rel="stylesheet" href="__BOWER__/jqnotifybar/css/jquery.notifyBar.css">
<script type="text/javascript" src="__BOWER__/jqnotifybar/jquery.notifyBar.js"></script>
<script type="text/javascript" src="__JS__/common.js"></script>
<script type="text/javascript">
var url = '__SELF__';
var no_pic = '__PUBLIC__/images/no-cover.png';
(function(){
var ThinkPHP = window.Think = {
"ROOT" : "__ROOT__", //当前网站地址
"APP" : "__APP__", //当前项目地址
"PUBLIC" : "__PUBLIC__", //项目公共目录地址
"DEEP" : "{:C('URL_PATHINFO_DEPR')}", //PATHINFO分割符
"MODEL" : ["{:C('URL_MODEL')}", "{:C('URL_CASE_INSENSITIVE')}", "{:C('URL_HTML_SUFFIX')}"],
"VAR" : ["{:C('VAR_MODULE')}", "{:C('VAR_CONTROLLER')}", "{:C('VAR_ACTION')}"]
}
})();
$(function(){
//导航高亮
$('.navbar-nav li').removeClass('active');
$('a.blog-nav-item[href="'+url+'"]').parent().addClass('active');
})
</script>
<!-- Your site ends -->
<block name="style"></block>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top blog-masthead">
<div class="container">
<div class="navbar-header">
<button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="javascript:;">Freelog</a>
</div>
<div class="blog-nav collapse navbar-collapse" id="example-navbar-collapse">
<ul class="nav navbar-nav">
<li><a class="blog-nav-item" href="{:U('/')}">首页</a></li>
<?php if (is_login()): ?>
<li><a class="blog-nav-item" href="{:U('/mine/')}">我的文章</a></li>
<?php endif ?>
<li>
<form class="navbar-form navbar-right" id="search" method="GET" action="/Search" role="search">
<div class="form-group input-group">
<input type="text" name="kw" class="form-control" placeholder="输入关键字搜索" value="{$kw|default=""}">
<span class="input-group-btn">
<button class="btn btn-default">
<span class="glyphicon glyphicon-search f20" aria-hidden="true"></span>
</button>
</span>
</div>
</form>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="javascript:;" role="button" aria-expanded="false"><if condition="is_login()">{:session('user.nickname')}</if></a></li>
<if condition="is_login()">
<li><a class="blog-nav-item" href="{:U('/user/profile')}">个人信息</a></li>
<li><a class="blog-nav-item" href="{:U('/user/logout')}" class="ajax-get">退出</a></li>
<else/>
<li><a class="blog-nav-item" href="{:U('/user/login')}">登录</a></li>
<li><a class="blog-nav-item" href="{:U('/user/reg')}">注册</a></li>
</if>
</ul>
</div>
</div>
</div>
<div class="container" id="main">
<block name="header">
<div class="blog-header">
<h1 class="blog-title">The Bootstrap Blog</h1>
<p class="lead blog-description">The official example template of creating a blog with Bootstrap.</p>
</div>
</block>
<div class="row">
<div class="col-sm-8 blog-main">
<block name="main"></block>
</div><!-- /.blog-main -->
<div class="col-sm-3 col-sm-offset-1 blog-sidebar">
<block name="sidebar"></block>
</div><!-- /.blog-sidebar -->
</div><!-- /.row -->
</div><!-- /.container -->
<footer class="blog-footer">
<p>Blog template built for <a href="http://getbootstrap.com">Bootstrap</a> by <a href="https://twitter.com/mdo">@mdo</a>.Modified by <a href="http://weibo.com/u/1342658313">@黑白世界4648</a></p>
<p>© {:date('Y', time())} Freelog. 由 Thinkphp 强力驱动.</p>
<p>
<a href="#">Back to top</a>
</p>
</footer>
<block name="script"></block>
</body>
</html>
~~~
- `<block name="style"></block>` 页面自定义样式区,
- `<block name="header"></block>` 博客标题区
- `<block name="main"></block>` 博客内容区
- `<block name="sidebar"></block>` 侧边栏区
- `<block name="script"></block>` 页面自定义js脚本区
再将index.html 页面改为继承base模板的
~~~
<extend name="Index/base" />
<block name="header">
<div class="blog-header">
<h4>{$title|default=""}</h4>
</div>
</block>
<block name="main">
<volist name="list" id="post" key="post_k">
<assign name="tpl" value="$post.type"/>
<switch name="tpl">
<case value="text"><include file="Index/text" /></case>
<case value="picture"><include file="Index/picture" /></case>
<case value="music"><include file="Index/music" /></case>
<case value="video"><include file="Index/video" /></case>
</switch>
</volist>
<empty name="list">
<div class="text-center">
<img src="__IMG__/logo-grey.png" alt="" width="135">
<br><br>
对不起,没有相应的文章
</div>
</empty>
{$_page}
</block>
<block name="sidebar">
<include file="Index/post_btn" />
<div class="sidebar-module sidebar-module-inset">
<h4>热门标签</h4>
<ul class="list-unstyled side-tracked-tag">
<volist name="tags" id="tag">
<li>
<a class="followed-tag clearfix" href="{:U('/')}?tag={$tag['title']}">
<span class="glyphicon glyphicon-tag" aria-hidden="true"></span>
<span class="">{$tag.title}</span>
</a>
</li>
</volist>
</ul>
</div>
<div class="sidebar-module">
<h4>归档</h4>
<ol class="list-unstyled">
<volist name="archive" id="vo">
<li><a href="{:U($vo['link'])}">{$vo.text}</a></li>
</volist>
</ol>
</div>
</block>
<block name="script">
<script type="text/javascript" src="__BOWER__/audiojs/audiojs/audio.min.js"></script>
<script src="__STATIC__/swipebox/js/jquery.swipebox.js"></script>
<link rel="stylesheet" href="__STATIC__/swipebox/css/swipebox.css">
<script type="text/javascript">
$(function(){
var single = audiojs;
single.events.ready(function() {
var a1 = single.createAll('', $('.single audio'));
});
//图片灯箱
$( '.swipebox' ).swipebox();
})
</script>
</block>
~~~
上面区块中,很多已经是最终现在的代码了。先无视掉。
# 总结
前端实现方面 主要涉及了三个问题,资源选择、资源引入、模板套用。
资源选择 大家可以参考 [代码家园](http://www.daimajiayuan.com/)、[最代码](http://www.zuidaima.com/) 这些个站长资源站点,时不时自己收藏一些 类似于最好的jquery组件之类文章。
模板套用 要会用模板常量和模板继承。后面还会讲到模板include包含。
- 序
- 前言
- 内容简介
- 目录
- 基础知识
- 起步
- 控制器
- 模型
- 模板
- 命名空间
- 进阶知识
- 路由
- 配置
- 缓存
- 权限
- 扩展
- 国际化
- 安全
- 单元测试
- 拿来主义
- 调试方法
- 调试的步骤
- 调试工具
- 显示trace信息
- 开启调试和关闭调试的区别
- netbeans+xdebug
- Socketlog
- PHP常见错误
- 小黄鸭调试法,每个程序员都要知道的
- 应用场景
- 第三方登录
- 图片处理
- 博客
- SAE
- REST实践
- Cli
- ajax分页
- barcode条形码
- excel
- 发邮件
- 汉字转全拼和首字母,支持带声调
- 中文分词
- 浏览器useragent解析
- freelog项目实战
- 需求分析
- 数据库设计
- 编码实践
- 前端实现
- rest接口
- 文章发布
- 文件上传
- 视频播放
- 音乐播放
- 图片幻灯片展示
- 注册和登录
- 个人资料更新
- 第三方登录的使用
- 后台
- 微信的开发
- 首页及个人主页
- 列表
- 归档
- 搜索
- 分页
- 总结经验
- 自我提升
- 进行小项目的锻炼
- 对现有轮子的重构和移植
- 写技术博客
- 制作视频教程
- 学习PHP的知识和新特性
- 和同行直接沟通、交流
- 学好英语,走向国际
- 如何参与
- 浏览官网和极思维还有看云
- 回答ThinkPHP新手的问题
- 尝试发现ThinkPHP的bug,告诉官方人员或者push request
- 开发能提高效率的ThinkPHP工具
- 尝试翻译官方文档
- 帮新手入门
- 创造基于ThinkPHP的产品,进行连带推广
- 展望未来
- OneThink
- ThinkPHP4
- 附录