模板引擎
是爲了使用戶界面與業務數據(內容)分離而產生的,它可以生成特定格式的文檔,用於網站的模板引擎就會生成一個標準的HTML文檔。
爲什麼要使用模板引擎
我們通過ajax獲取到數據後,需要把數據渲染到頁面,在學習模板引擎前,我們的做法是大量的拼接字符串,對於結構簡單的頁面,這麼做還行
但是如果頁面結構很複雜,使用拼串的話代碼可閱讀性非常的差,而且非常容易出錯,後期代碼維護也是相當的麻煩。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="user">
<p>姓名: xx</p>
<p>年齡: xx</p>
<p>性別: xx</p>
<p>描述: xx</p>
</div>
<script>
// 找對象
var user = document.getElementById("user");
// 從後臺通過 ajax 獲取數據
var obj = {
name: "小王",
age: 18,
sex: "男",
desc: "猥瑣"
}
// 字符串拼接
var htmlStr = " <p>姓名: " + obj.name + "</p> " +
" <p>年齡: " + obj.age + "</p> " +
" <p>性別: " + obj.sex + "</p> " +
" <p>描述: " + obj.desc + "</p> ";
user.innerHTML = htmlStr;
// 缺點:
// 1. html標籤代碼 和 js 代碼混在一起, 代碼冗餘
// 2. 字符串拼接非常麻煩, 維護起來不方便
</script>
</body>
</html>
總結來說拼串渲染兩大缺點:
-
js中大量充斥着 html 結構拼串代碼, 很冗餘, 可讀性差
-
字符串拼接很麻煩, 且維護起來也很麻煩, 容易出錯
常見的模板引擎
BaiduTemplate:http://tangram.baidu.com/BaiduTemplate/
velocity.js:https://github.com/shepherdwind/velocity.js/
ArtTemplate:https://github.com/aui/artTemplate
artTemplate是使用最廣泛,效率最高的模板引擎,需要大家掌握。
artTemplate的使用
github地址(https://github.com/aui/art-template)
中文api地址(https://aui.github.io/art-template/docs/ )
artTemplate入門
1.引入模板引擎的js文件
<script src="template-web.js"></script>
2.準備模板
<!--
指定了type爲text/html後,這一段script標籤並不會解析,也不會顯示。
-->
<script type="text/html" id="myTmp">
<p>姓名:隔壁老王</p>
<p>年齡:18</p>
<p>技能:查水錶</p>
<p>描述:年輕力氣壯</p>
</script>
3.準備數據
//3. 準備數據,數據是後臺獲取的,可以隨時變化
var json = {
userName:"隔壁老王",
age:18,
skill:"查水錶",
desc:"年輕氣壯"
}
4.將模板與數據進行綁定
//第一個參數:模板的id
//第二個參數:數據
//返回值:根據模板生成的字符串。
var html = template("myTmp", json);
console.log(html);
5.修改模板
<script type="text/html" id="myTmp">
<p>姓名:{{userName}}</p>
<p>年齡:{{age}}</p>
<p>技能:{{skill}}</p>
<p>描述:{{desc}}</p>
</script>
6.將數據顯示到頁面
var div = document.querySelector("div");
div.innerHTML = html;
artTemplate標準語法
if語法
{{if gender='男'}}
<div class="man">
{{else}}
<div class="woman">
{{/if}}
each語法
<!--
1. {{each data}} 可以通過$value 和 $index獲取值和下標
2. {{each data v i}} 自己指定值爲v,下標爲i
-->
{{each data v i}}
<li>
<a href="{{v.url}}">
<img src="{{v.src}}" alt="">
<p>{{v.content}}</p>
</a>
</li>
{{/each}}
注意:
//如果返回的數據是個數組,必須使用對象進行包裹,因爲在{{}}中只寫書寫對象的屬性。
var html = template("navTmp", {data:info});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.item {
float: left;
width: 320px;
border: 1px solid #0094ff;
overflow: hidden;
margin: 10px;
padding: 5px;
}
.item .title {
display: block;
width: 100%;
position: relative;
}
.title img {
display: block;
height: 180px;
width: 100%;
}
.title span {
position: absolute;
right: 20px;
bottom: 0px;
width: 50px;
text-align: center;
background-color: lightgray;
color: gray;
font-size: 13px;
border-radius: 5px 5px 0 0;
}
.content {
height: 100px;
padding: 10px;
overflow: hidden;
}
.content a {
text-decoration: none;
color: black;
font-family: "微軟雅黑";
font-size: 16px;
}
.content p {
color: gray;
font-size: 13px;
font-family: "微軟雅黑";
margin-bottom: 0;
}
.f_l {
float: left;
}
.f_r {
float: right;
}
.clearfix::before,
.clearfix::after {
content: '';
display: block;
line-height: 0;
height: 0;
clear: both;
visibility: hidden;
}
.info {
line-height: 25px;
}
.info img {
width: 20px;
height: 20px;
vertical-align: middle;
margin-right: 10px;
}
.info a {
color: gray;
text-decoration: none;
font-size: 12px;
height: 20px;
line-height: 20px;
margin: 0 10px;
}
</style>
</head>
<body>
<input type="number" id="num">
<button id="btn">獲取數據</button>
<div class="items">
</div>
</body>
<script src="./js/jquery.min.js"></script>
<script src="./js/template-web.js"></script>
<script type="text/html" id="tpl">
{{ each items v i }}
<!--div作爲容器-->
<div class="item clearfix">
<a href="#" class='title'>
<img src="{{ v.img }}" alt="" />
<span>{{ v.time }}</span>
</a>
<div class="content">
<a href="#">{{ v.title }}</a>
<p>{{ v.novel }}</p>
</div>
<div class="info clearfix">
<a href="#" class='f_l'>
<img src="{{ v.icon }}" alt="" />{{ v.name }}</a>
<a href="#" class='f_r'>信息:{{ v.messNum }}</a>
<a href="#" class='f_r'>❤: {{ v.starNum }}</a>
<a href="#" class='f_r'>贊:{{ v.goodNum }}</a>
</div>
</div>
{{ /each }}
</script>
<script>
// 需求: 點擊獲取數據, 根據input框的值, 獲取對應條數的數據, 進行頁面渲染(模板引擎)
$('#btn').click(function() {
var num = $('#num').val(); // 獲取input的框的值
// 發送請求, 獲取數據
$.ajax({
type: "get",
url: "smzdm.php",
data: {
num: num
},
dataType: "json",
success: function( info ) {
console.log( info );
// 將模板和數據相結合, 渲染頁面 template( 模板id, 數據對象 );
// info 中有屬性 items 可以用於遍歷
var htmlStr = template( "tpl", info );
$('.items').html( htmlStr );
}
})
})
</script>
</html>
//smzdm.php
<?php
header('content-type:application/json;charset=utf-8');
// 讀取數據 -> 一共 10 條數據
$arr = json_decode(file_get_contents('data/smzdm_novels.json'));
// 總個數
$totalNum = count($arr);
// 定義返回的信息
$message = '數據獲取成功';
// 獲取輸出的個數
if( isset( $_GET['num'] ) ){
$outputNum = $_GET['num'];
// 判斷是否超過總個數
if( $outputNum > $totalNum ) {
$message = 'num 超出最大值,全部返回';
$outputNum = $totalNum;
}
// 如果小於等於0 按 1 處理
if ( $outputNum <= 0 ) {
$message = '至少會返回 1 條數據';
$outputNum = 1;
}
}else{
// 沒傳, 按最大值處理
$message = 'num 未設置 全部返回';
$outputNum = $totalNum;
}
// 從數組中隨機取出幾個下標
// 需要注意: 如果取出一個返回一個下標, 取出多個返回的是索引數組形式, 所以需要對取出一個進行處理
$randomKeyArr = array_rand($arr, $outputNum);
if ( $outputNum == 1 ) {
$randomKeyArr = [ "0" => $randomKeyArr ];
}
// 定義 新數組, 根據索引從數組中取數據
$items = [];
for( $i = 0; $i < count( $randomKeyArr ); $i++ ){
$items[ $i ] = $arr[ $randomKeyArr[$i] ];
}
echo json_encode( array(
'message'=> $message,
'items' => $items
));
// 延遲
sleep(1);
?>