notebooks
  • notebooks
  • _planning
    • 2022 OKR
    • basketball
    • swimming
  • communication
    • Dubbo
    • Kafka
    • Messaging
    • RPC
    • Thrift
  • computation
    • map-reduce
  • cs-basic-knowledge
    • computer-architecture
    • data-structure-and-algorithms
    • networks
    • os
  • devops
    • Docker
    • Linux
    • Prometheus
    • operations
    • security
    • trouble-shooting
  • distributed-knowledge
    • Zookeeper_CMD
    • distributed-system
  • game-engine
    • Unity
  • others
    • appium使用
  • protocols
    • http(s)协议
    • 官方链接
    • sip
  • storage
    • Elasticsearch
    • GuavaCache
    • MySQL
    • MySQL_CMD
    • NoSQL
    • Redis
    • Redis_CMD
  • system-design
    • system-design
  • tools
    • Git
    • IDEA
    • Mac
    • VScode
    • Vim
  • _working
    • doc-template
      • backend-design-review
      • correction-of-error
      • service-review
    • process
      • domain-backup
      • oncall
  • blogs
    • history
      • 8088/8086微处理器
      • 8088/8086指令系统
      • CSS-DOM
      • CSS定位
      • CSS工作原理
      • CSS控制背景
      • CSS浮动布局
      • CSS盒模型
      • Chrome开发者工具使用方法
      • DOM
      • Django Model模型层学习
      • Django-REST-framework Serializers学习
      • Django-REST-framework Views和ViewSets学习
      • Django View视图层学习
      • Gvim下Emmet安装及使用教程
      • HTTP协议简介
      • HashMap原理初探
      • JavaScript简史
      • JavaScript语法
      • Java内存模型和GC机制
      • Java基础——Lambda学习
      • Java基础——方法引用
      • Java基础——枚举类型
      • Java类加载机制
      • KMP算法
      • Kafka学习
      • Linux下用命令行编译Java程序
      • MathJax简介和基本用法
      • Python实现常见数据结构
      • Python装饰器总结
      • TCP协议的三次握手和四次挥手
      • Thrift学习
      • asyncio学习
      • markdown的常用语法
      • 修改hosts文件实现翻墙
      • 充实文档的内容
      • 关系数据库
      • 关系数据库标准语言SQL(一)
      • 关系数据库标准语言SQL(二)
      • 关系数据理论
      • 关系查询处理和查询优化
      • 内联元素和块级元素
      • 剑指offer算法题练习
      • 动态创建标记
      • 图形化用户界面
      • 在Eclipse中使用Maven构建Java Web项目
      • 增加微博秀遇到的一些问题
      • 处理机调度
      • 如何用github和hexo搭建个人博客
      • 存储管理
      • 存储系统的层次结构
      • 学习模仿lionhit网站首页的过程总结
      • 实用的GitHub小技巧
      • 并发控制
      • 循环与分支程序设计
      • 指令系统的设计
      • 指令级并行及其开发——硬件方法
      • 搭建自己的VPN服务器
      • 操作系统用户界面
      • 数据库安全性
      • 数据库完整性
      • 数据库恢复技术
      • 数据库绪论
      • 数据库编程
      • 数据库设计
      • 数据抽象
      • 文件系统
      • 文法和语言
      • 最佳实践
      • 案例研究:JavaScript图片库
      • 案例研究:图片库改进版
      • 汇编语言程序格式
      • 汇编语言程序设计基础知识
      • 流水线技术
      • 深度优先搜索和广度优先搜索
      • 牛客网——网易2017秋招编程题集合
      • 用JavaScript实现动画效果
      • 第一篇博客
      • 经典排序算法总结(Java实现)
      • 经典查找算法总结(Java实现)
      • 综合示例
      • 编译原理引论
      • 背包、队列和栈
      • 虚拟机安装Linux系统及常用软件
      • 计算机操作系统绪论
      • 计算机系统结构的基础知识
      • 设备管理
      • 设计模式之代理模式
      • 设计模式之单例模式
      • 设计模式之工厂模式
      • 设计模式之策略模式
      • 设计模式之观察者模式
      • 词法分析
      • 进程管理
      • 闭包
      • 阻止Google自动跳转到香港服务器的方法
      • 项目部署过程
  • programming-language
    • C#
      • C#
    • C&C++
      • C
    • C&C++
      • C++
    • Java
      • GoogleGuice
    • Java
      • JVM
    • Java
      • Java
    • Java
      • Maven
    • Java
      • Mybatis
    • Java
      • Spring知识
    • Java
      • SpringBoot
    • Java
      • Tomcat
    • Python
      • Python
    • Shell
      • Shell
  • wheels
    • dcc
      • 产品调研
      • 方案设计
    • red-envelope
      • 方案设计
    • short-url
      • 短链接服务
    • sso
      • 方案设计
Powered by GitBook
On this page
  • 项目简介
  • 原始资料
  • 站点结构
  • 页面结构
  • 设计
  • CSS
  • 颜色
  • 布局
  • 版式
  • 标记
  • JavaScript
  • 页眉突出显示
  • JavaScript幻灯片
  • 内部导航
  • JavaScript图片库
  • 增强表格
  • 增强表单
  • 压缩代码
  1. blogs
  2. history

综合示例

项目简介

为世界著名的乐队Jay Skript and the Domsters设计一个网站。

原始资料

有关乐队的介绍材料、巡演日程,以及一些照片。

站点结构

站点文件夹目录结构:

  • /images

  • /styles

  • /scripts

要创建的页面:

  • /Home

  • /About

  • /Photos

  • /Live

  • /Contact

对应如下文件:

  • index.html

  • about.html

  • photos.html

  • live.html

  • contact.html

页面结构

站点每个页面分成几个区域:

  • 头部区域包含站点的品牌性信息,也是放logo的地方。这个区域要使用<header>元素。

  • 导航区域包含一组链接,指向各个页面。这个区域使用<nav>元素。

  • 内容区域包含每一页的实质性内容,这个区域使用<article>元素。

模板代码:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <title>Jay Skript and the Domsters</title>
</head>
<body>
		<header>
		        <nav>
		                <ul>
		                        <li><a href="index.html">Home</a></li>
		                        <li><a href="about.html">About</a></li>
		                        <li><a href="photos.html">Photos</a></li>
		                        <li><a href="live.html">Live</a></li>
		                        <li><a href="contact.html">Contact</a></li>
		                </ul>
		        </nav>
		</header>
		<article>
		</article>
</body>
</html> 

设计

外观设计

CSS

建议把所有CSS分别放在几个文件:

  • layout.css 整体布局

  • color.css 颜色

  • typography.css 版式

这些样式表都可以导入到一个基本的样式表中:

@import url(layout.css);
@import url(color.css);
@import url(typography.css);

把包含这三行代码的文件保存为basic.css,并放在styles文件夹中。如果想添加一个新样式表或者删除一个样式,只要编辑basic.css即可。在模板的<head>元素中通过<link>元素引入这个基本样式表,然后在页面<header>中添加一个<img>标签,指向logo图片。也可以向<article>中添加一些临时性填充文本:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <title>Jay Skript and the Domsters</title>
		<link rel="stylesheet" href="styles/basic.css" media="screen" />
</head>
<body>
		<header>
				<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
		        <nav>
		                <ul>
		                        <li><a href="index.html">Home</a></li>
		                        <li><a href="about.html">About</a></li>
		                        <li><a href="photos.html">Photos</a></li>
		                        <li><a href="live.html">Live</a></li>
		                        <li><a href="contact.html">Contact</a></li>
		                </ul>
		        </nav>
		</header>
		<article>
				<h1>Lorem Ipsum Dolor</h1>
				<p>Lorem assumenda nihil commodi sequi nemo velit accusamus nulla, magnam a Possimus veniam suscipit omnis culpa doloremque. Eligendi corporis eius quae similique eius Quam nostrum molestias a nemo illo corrupti?</p>
		</article>
</body>
</html> 

颜色

记住,不管为哪个元素应用什么颜色,都要同时给它一个背景色。否则,就有可能导致意外,看不到某些文本。

body {
        color:#fb5;
		background-color: #334;
}
a:link{
		color:#445;
		background-color: #eb6;
}
a:visited{
		color:#345;
		background-color: #eb6;
}
a:hover{
		color:#667;
		background-color: #fb5;
}
a:active{
		color:#778;
		background-color: #ec8;
}
header{
		color:#ec8;
		background-color: #334;
		border-color: #667;
}
header nav {
        color: #445;
		background-color: #789;
		border-color: #667;
}
article {
        color: #223;
		background-color: #edc;
		border-color: #667;
}
header nav ul {
        border-color: #99a;
}
header nav a:link,header nav a:visited {
        color:#eef;
		background-color: #transparent;
		border-color: #99a;
}
header nav a:hover {
        color:#445;
		background-color: #eb6;
}
header nav a:active {
        color:#667;
		background-color: #ec8;
}
article img {
        border-color: #ba9;
		outline-color: #dcb;
}
#imagegally a {
        background-color: transparent;
} 

布局

section,header,article,nav {
        display:block;
}
* {
        padding:0;
		margin:0;
}
body {
        margin:1em 10%;
		background-image: url(..images/background.gif);
		background-attachment: fixed;
		background-position: top left;
		background-repeat: repeat-x;
		max-width: 80em;
}
header {
        background-image: url(..images/guitarist.gif);
		background-repeat: no-repeat;
		background-position: bottom right;
		border-width: .1em;
		border-style: solid;
		border-bottom-width: 0;
}
header nav{
		background-image: url(..images/header navbar.gif);
		background-position: bottom left;
		background-repeat: repeat-x;
		border-width: .1em;
		border-style: solid;
		border-bottom-width: 0;
		border-top-width: 0;
		padding-left: 10%;
}
header nav ul {
        width:100%;
		overflow:hidden;
		border-left-width: .1em;
		border-left-style: solid;
}
header nav li {
        display:inline;
}
header nav li a {
        display: block;
		float: left;
		padding:.5em 2em;
		border-right: .1em solid;
}
article {
        border: .1em;
		border-style: solid;
		border-top-width: 0;
		padding: 2em 10%;
		line-height: 1.8em;
}
article img {
        border-width: .1em;
		border-style: solid;
		outline-width: .1em;
		outline-style: solid;
}

版式

字体和大小显然应该放在版式文件中,而外边距和内边距难以说清,这里将内边距信息放在布局中,外边距信息放在版式中:

body {
        font-size: 76%;
		font-family: "Helvetica","Arial",sans-serif;
}
body * {
        font-size: 1em;
}
a {
        font-weight: bold;
		text-decoration: none;
}
header nav {
        font-family: "Lucida Grande","Helvetica","Arial",sans-serif;
}
header nav a {
        text-decoration: none;
		font-weight: bold;
}
article {
        line-height: 1.8em;
}
article p {
        margin: 1em 0;
}
h1 {
        font-family: "Georgia","Times New Roman",sans-serif;
		font: 2.4em normal;
}
h2 {
        font-family: "Georgia","Times New Roman",sans-serif;
		font: 1.8em normal;
		margin-top: 1em;
}
h3 {
        font-family: "Georgia","Times New Roman",sans-serif;
		font: 1.4em normal;
		margin-top: 1em;
}
#imagegallery li{
		list-style-type: none;
}
textarea {
        font-family:  "Helvetica","Arial",sans-serif;
}

标记

主页index.html添加一段介绍性文字:

<p id="intro">
Welcome to the official website of Jay Skript and the Domsters.
Here,you can <a href="about.html" title="About">learn more about the band</a>,view <a href="photos.html" title="Photos">photos of the band</a>,find out about <a href="live.html" title="Tout date">tour dates</a> and <a href="contact.html" title="Contact">get in touch with the band</a>.
</p>

JavaScript

在编写DOM脚本之前,必须先确定怎么组织JavaScript文件。如果站点需要很多长长的脚本,那最好把它分割成几个小文件。本站很简单,所需的JavaScript代码也不长。为了减少请求的数量,将所有脚本放在global.js文件里。需要添加的函数:addLoadEvent函数,insetAfter函数,addClass函数。

页眉突出显示

修改color.css文件,添加为here类定义的样式:

header nav a.here:link,
header nav a.here:visited,
header nav a.here:hover,
header nav a.here:active{
		color:#eef;
		background-color: #799;
}

增加函数highlightPage:

function highlightPage(){
		if(!document.getElementsByTagName) return false;
		if(!document.getElementById) return false;
		var headers=document.getElementsByTagName("header");
		if(headers.length==0) return false;
		var navs=headers[0].getElementsByTagName("nav");
		if(navs.length==0) return false;
		var links=navs[0].getElementsByTagName("a");
		var linkurl;
		for(var i=0;i<links.length;i++){
				linkurl=links[i].getAttribute("href");
				if(window.location.href.indexOf(linkurl)!=-1){  //比较两者地址(字符串)
						links[i].className="here";
				}
		}
}
function highlightPage(){
		if(!document.getElementsByTagName) return false;
		if(!document.getElementById) return false;
		var headers=document.getElementsByTagName("header");
		if(headers.length==0) return false;
		var navs=headers[0].getElementsByTagName("nav");
		if(navs.length==0) return false;
		var links=navs[0].getElementsByTagName("a");
		var linkurl;
		for(var i=0;i<links.length;i++){
				linkurl=links[i].getAttribute("href");
				if(window.location.href.indexOf(linkurl)!=-1){ 
						links[i].className="here";
						var linktext=links[i].lastChild.nodeValue.toLowerCase();  //转换成小写
						document.body.setAttribute("id",linktext);
				}
		}
}

更新layout.css,添加以下代码:

#about header {
        background-image: url(../images/lineup.gif);
}
#photos header {
        background-image: url(../images/basshead.gif);
}
#live header {
        background-image: url(../images/bassist.gif);
}
#contact header {
        background-image: url(../images/drummer.gif);
}

如此一来,每个页面的头部就会应用不同的背景图像了。

JavaScript幻灯片

需要用到moveElement函数。还要创建幻灯片元素并准备相应链接:

function prepareSlideshow(){
		if(!document.getElementsByTagName) return false;
		if(!document.getElementById) return false;
		if(!document.getElementById("intro")) return false;
		var intro=document.getElementById("intro");
		var slideshow=document.createElement("div");
		slideshow.setAttribute("id","slideshow");
		var frame=document.createElement("img");
		frame.setAttribute("src","images/frame.gif");
		frame.setAttribute("alt","");
		frame.setAttribute("id","frame");
		var preview=document.createElement("img");
		preview.setAttribute("src","images/slideshow.gif");
		preview.setAttribute("alt","a glimpse of what awaits you");
		preview.setAttribute("id","preview");
		slideshow.appendChild(preview);
		insertAfter(slideshow,intro);
		var links==document.getElementsByTagName("a");
		var destination;
		for(var i=0;i<links.length;i++){
				links[i].onmouseover=function(){
						destination=this.getAttribute("href");
						if(destination.indexOf("index.html")!=-1){
								moveElement("preview",0,0,5);
							}
						if(destination.indexOf("about.html")!=-1){
								moveElement("preview",-150,0,5);
							}
						if(destination.indexOf("photos.html")!=-1){
								moveElement("preview",-300,0,5);
							}
						if(destination.indexOf("live.html")!=-1){
								moveElement("preview",-450,0,5);
							}
						if(destination.indexOf("contact.html")!=-1){
								moveElement("preview",-600,0,5);
							}
					}
			}
	}

内部导航

制作About页面。在about.html的<article>元素添加如下标记:

<h1>About the band</h1>
				<nav>
				        <ul>
								<li><a href="#jay">Jay Skript</a></li>
								<li><a href="#domsters">The Domsters</a></li>
				        </ul>
				</nav>
				<section id="jay">
				        <h2>Jay Skript</h2>
				        <p>Jay Skript is going to rock your world!</p>
				        <p>Together with his compatriots the Domsters,Jay is set for world domination,Just you wait and see.</p>
				        <p>Jay Skript has been on the scene since the mid 1990s.His talent hasn't always been recognized or fully appreciated.In the early days,he was often unfavorably compared to bigger,similarly named artists.That is all in the past now.</p>
				</section>
				<section id="domsters">
				        <h2>The Domsters</h2> 
						<p>The Domsters have been around,in one form or another,for almost as long.It is only in the past few years that the Domsters have settled down to their current,stable lineup.Now they are a rock-solid bunch:methodical and dependable.</p>
				</section>

但是页面略长,而<nav>元素中包含的内部链接就是解决这个问题。单击<nav>中的每个链接,都会跳到带有相应id属性的<section>。使用JavaScript和DOM,选择性地每次只显示其中一个部分(section):

function showSection(id){
		var sections=document.getElementsByTagName("section");
		for(var i=0;i<sections.length;i++){
				if(sections[i].getAttribute("id")!=id){
						sections[i].style.display="none";
					}else{
						sections[i].style.display="block";
							}
			}
	}

然后还需要在<article>中的<nav>所包含的链接被单击时调用showSection函数:

function prepareInternalnav(){
		if(!document.getElementsByTagName) return false;
		if(!document.getElementById) return false;
		var articles=document.getElementsByTagName("article");
		if(articles.length==0) return false;
		var navs=articles[0].getElementsByTagName("nav");
		if(navs.length==0) return false;
		var nav=navs[0];
		var links=nav.getElementsByTagName("a");
		for(var i=0;i<links.length;i++){
				var sectionId=links[i].getAttribute("href").split("#")[1];
				if(!document.getElementById(sectionId)) continue;
				document.getElementById(sectionId).style.display="none";
				links[i].destination=sectionId;
				links[i].onclick=function(){
						showSection(this.destination);
						return false;
					}
			}
	}

JavaScript图片库

接下来制作photos.html

<h1>Photos of the band</h1>
				<ul id="imagegallery">
				        <li><a href="images/photos/concert.jpg" title="The crowd goes wild"><img src="images/photos/thumbnail_concert.jpg" alt="the band in concert" /></a></li>
				        <li><a href="images/photos/bassist.jpg" title="An atmospheric moment"><img src="images/photos/thumbnail_bassist.jpg" alt="the bassist"></a></li>
				        <li><a href="images/photos/guitarist.jpt" title="Rocking out"><img src="images/photos/thumbnail_guitarist.jpg" alt="the guitarist"></a></li>
				        <li><a href="images/photos/crowd.jpg" title="Encore!Encore!"><img src="images/photos/thumbnail_crowd.jpg" alt="the audience"></a></li>
				</ul>

更新layout.css,添加:

#imagegallery li{
	display:inline;
}

增强表格

制作live.html页面

<h1>Tour dates</h1>
				<table summary="when and where you can see the band">
				        <thead>
				                <tr>
				                        <th>Date</th>
				                        <th>City</th>
				                        <th>Venue</th>
				                </tr>
				        </thead>
				        <tbody>
				                <tr>
				                        <td>June 9th</td>
										<td>Portland,<abbr title="Oregon">OR</abbr></td>
				                        <td>Crystal Ballroom</td>
				                </tr>
				                <tr>
				                        <td>June 10th</td>
										<td>Seattle,<abbr titlt="Washington">WA</abbr></td>
				                        <td>Crocodile Cafe</td>
				                </tr>
				                <tr>
				                        <td>June 12th</td>
										<td>Sacramento,<abbr title="California">CA</abbr></td>
				                        <td>Torch Club</td>
				                </tr>
				                <tr>
				                        <td>June 17th</td>
										<td>Austin,<abbr title="Texas">TX</abbr></td>
				                        <td>Speakeasy</td>
				                </tr>
				        </tbody>
				</table>

更新layout.css:

td{
			padding:.5em 3em;
		}

更新color.css:

th{
				color:#edc;
				background-color:#455;
		}
tr td{
				color:#223;
				background-color:#eb6;
		}

在global.js中添加stripeTables函数、highlightRows函数和displayAbbreviations函数。 改动:

  • highlightRows:没有直接运用样式,而是使用addClass函数添加了highlight类。

  • displayAbbreviations:将content改为article元素。

更新layout.css

dl{
				overflow:hidden;
		}
dt{
				float:left;
		}
dd{
				float:left;
		}

更新typography.css

dt{
				margin-right:1em;
		}
dd{
				margin-right:3em;
		}

更新color.css

tr.odd td{
				color:#223;
				background-color:#ec8;
		}
tr.highlight td{
				color:#223;
				background-color:#cba;
		}

增强表单

构建一个联系表单

<h1>Contact the band</h1>
				<form method="post" action="submit.html">
				<fieldset>
				        <p>
				                <label for="name">Name:</label>
				                <input type="text" id="name" name="name" placeholder="Your name" required="required">
				        </p>
				        <p>
				                <label for="email">Email:</label>
				                <input type="email" id="email" name="email" placeholder="Your email address" required="required" />
				        </p>
				        <p>
				                <label for="message">Message:</label>
								<textarea cols="45" rows="7" id="message" name="message" required="required" placeholder="Write your message here."></textarea>
				        </p>
						<input type="submit" value="Send" />
				</fieldset>
				</form>

更新layou.css

label{
				display:block;
		}
fieldset{
				border:0;
		}

然后基于模板创建submit.html,添加如下内容:

<h1>Thanks!</h1>
<p>Thanks for contacting us.We will get back to you as soon as we can.</p>

字段标签

表单中有三个字段:name、email和message。每个字段都有一个对应的<label>标签。很多浏览器会对label元素添加默认行为:如果label中的文本被单击,关联的表单字段就会获得焦点。但并不是所有浏览器都实现了该行为,写个函数保证在所有浏览器都有此行为:

function focusLabels(){
				if(!document.getElementsByTagName) return false;
				var labels=document.getElementsByTagName("label");
				for(var i=0;i<labels.length;i++){
								if(!labels[i].getAttribute("for")) continue;
								labels[i].onclick=function(){
												var id=this.getAttribute("for");
												if(!document.getElementById(id)) return false;
												var element=document.getElementById(id);
												element.focus();
										}
						}
		}

表单验证

在使用JavaScript编写验证表单的脚本时,记住三件事:

  • 验证脚本写得不好,反而不如没有验证。

  • 千万不要完全依赖JavaScript。客户端验证并不能取代服务器端的验证。

  • 客户端验证的目的在于帮助用户填好表单,避免他们提交未完成的表单,从而节省他们的时间。

function isFilled(){
				if(field.value.replace(' ','').length==0) return false;
				var placeholder=field.placeholder||field.getAttribute('placeholder');
				return (field.value!=placeholder);
		}

提交表单

function getHTTPObject() {
  if (typeof XMLHttpRequest == "undefined")
    XMLHttpRequest = function () {
      try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
        catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
        catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP"); }
        catch (e) {}
      return false;
  }
  return new XMLHttpRequest();
}

function displayAjaxLoading(element) {
    // Remove the existing content.
  while (element.hasChildNodes()) {
      element.removeChild(element.lastChild);
  }
  //  Create a loading image.
  var content = document.createElement("img");
  content.setAttribute("src","images/loading.gif");
  content.setAttribute("alt","Loading...");
  // Append the loading element.
  element.appendChild(content);
}

function submitFormWithAjax( whichform, thetarget ) {
  
  var request = getHTTPObject();
  if (!request) { return false; }

  // Display a loading message.
  displayAjaxLoading(thetarget);

  // Collect the data.
  var dataParts = [];
  var element;
  for (var i=0; i<whichform.elements.length; i++) {
    element = whichform.elements[i];
    dataParts[i] = element.name + '=' + encodeURIComponent(element.value);
  }
  var data = dataParts.join('&');

  request.open('POST', whichform.getAttribute("action"), true);
  request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

  request.onreadystatechange = function () {
    if (request.readyState == 4) {
        if (request.status == 200 || request.status == 0) {
          var matches = request.responseText.match(/<article>([\s\S]+)<\/article>/);
          if (matches.length > 0) {
            thetarget.innerHTML = matches[1];
          } else {
            thetarget.innerHTML = '<p>Oops, there was an error. Sorry.</p>';
          }
        } else {
          thetarget.innerHTML = '<p>' + request.statusText + '</p>';
        }
    }
  };

  request.send(data);
   
  return true;
};

压缩代码

Previous经典查找算法总结(Java实现)Next编译原理引论

Last updated 3 years ago

此时模板图:

如图:

如下:

如图所示: 利用highlightPage函数,还可以通过给每个页面的body元素添加id属性,可以为每个页面应用不同的样式。 新的highlightPage:

效果如图:

效果如图:

在global.js中添加showPic函数和preparePlaceholder函数。微小改动:将description文本放到了placeholder图像上方。 效果预览:

效果如图:

见

最佳实践
综合示例2
综合示例3
综合示例5
综合示例4
综合示例1
综合示例7
综合示例6
综合示例8