React官網示例講解

前言

可能大家會問:“官網示例那麼簡單,有必要講解嗎?”,我的看法是:“非常需要!”。一般而言,官方文檔是學習新知識最好的去處,你可以瞭解它的理念、思想、模式和API等等,可謂是無所不包。相對來說,官網的Sample就是能快速的瞭解和切入的直觀體現。因此,今天來看看官網的示例要告訴我們什麼,相信它對感興趣React但是不是很瞭解的人可以有個感性的瞭解。

什麼是React(個人見解/官方簡介轉述)

  1. 它只做UI層面的事,你可以理解為是Web Component的特殊實現
  2. Virtual DOM,就一個字:“快”,同時支持服務端渲染
  3. 數據流,單向的數據綁定足夠應付大部分的業務場景,同時使得數據和事件的流動變得清晰

怎麼開始用上React

這裡我們先不用Webpack、gulp這些這麼“高級”的工具,方便小白入門。
我們直接引入對應的腳本更加方便,大概是這樣子的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Sample 1</title>
</head>
<body>
<div id="container"></div>
<script src="http://cdn.bootcss.com/babel-core/5.8.34/browser.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-with-addons.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-dom.js"></script>
<script type="text/babel">
var mountNode = document.getElementById('container');

var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>
}
});

ReactDOM.render(<HelloMessage name="SASUKE40" />, mountNode);
</script>

</body>
</html>

這是官網的第一個示例,當然官網略去了很多東西沒說。
先說一下上面代碼我加了的東西:

  1. browser.jsbabel的瀏覽器版本,babel是一個很酷的東西,自己Google下就知道有多酷。提示一下,千萬別急著用babel6,你會用哭的~
  2. react就不必多說了,我們的主角
  3. react-dom是最近從react拆出來的,以前是包在react中的

細心的朋友可能看到type="text/babel"這個奇怪的類型屬性,其實它是為了讓babel能去轉換jsx成瀏覽器讀得懂兼容較好的JavaScript

示例初步講解

為什麼說初步呢?因為深挖底層具體的動作,可能很多人都會暈,所以只講表層我們看的到的東西。

第一個官方示例主要分成兩個步驟:

  1. 創建React類,使用React.createClass創建,傳入一個object,
    這個object有個成員屬性render返回jsx
  2. 用ReactDOM如渲染並掛載到某個具體的DOM節點上

    額外的Tip:在這裡的<div>Hello {this.props.name}</div>這一部分並不是HTML,而是貨真價實的JavaScript,並且創建出來對象是React實例,並不是HTML的DOM節點。

使用React在這個示例的好處

可以自定義標籤屬性,在渲染的時候可以插入到內容中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Sample 2</title>
</head>
<body>
<div id="container"></div>
<script src="http://cdn.bootcss.com/babel-core/5.8.34/browser.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-with-addons.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-dom.js"></script>
<script type="text/babel">
var mountNode = document.getElementById('container');

var Timer = React.createClass({
getInitialState: function() {
return {secondsElapsed: 0};
},
tick: function() {
this.setState({secondsElapsed: this.state.secondsElapsed + 1})
},
componentDidMount: function() {
this.interval = setInterval(this.tick, 1000);
},
componentWillUnmount: function() {
clearInterval(this.interval);
},
render: function() {
return (
<div>過去了:{this.state.secondsElapsed}秒</div>
)
}
});

ReactDOM.render(<Timer/>, mountNode);
</script>

</body>
</html>

這個示例多了好多:

  1. getInitialState是一個關鍵的成員屬性,它可以初始化state,在render中可以調用this.state.xxx就能拿到
  2. tick是一個自定義的成員屬性,其中this.setState是React類的關鍵方法,可以修改state的值
  3. componentDidMount顧名思義,在掛載後執行一些東西,這裡是弄了個定時器
  4. componentWillUnmount也顧名思義,將要卸載的時候做點事情,良好的編碼習慣,這裡清除定時

示例3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Sample 3</title>
</head>
<body>
<div id="container"></div>
<script src="http://cdn.bootcss.com/babel-core/5.8.34/browser.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-with-addons.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-dom.js"></script>
<script type="text/babel">
var mountNode = document.getElementById('container');

var TodoList = React.createClass({
render: function() {
var createItem = function(item) {
return <li key={item.id}>{item.text}</li>;
};
return <ul>{this.props.items.map(createItem)}</ul>;
}
});
var TodoApp = React.createClass({
getInitialState: function() {
return {items: [], text: ''};
},
onChange: function(e) {
this.setState({text: e.target.value});
},
handleSubmit: function(e) {
e.preventDefault();
var nextItems = this.state.items.concat([{text: this.state.text, id: Date.now()}]);
var nextText = '';
this.setState({items: nextItems, text: nextText});
},
render: function() {
return (
<div>
<h3>TODO</h3>
<TodoList items={this.state.items} />
<form onSubmit={this.handleSubmit}>
<input onChange={this.onChange} value={this.state.text} />
<button>{'Add #' + (this.state.items.length + 1)}</button>
</form>
</div>
);
}
});

ReactDOM.render(<TodoApp />, mountNode);
</script>

</body>
</html>

關鍵點:

  1. 標籤可以嵌套
  2. 可以些一些事件,以自定義事件函數體現,不管這裡的是JavaScript的事件,並不是DOM節點上定義的
  3. 列表組件定義的一種推薦寫法:this.props.items.map傳入單個組件

示例4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Sample 4</title>
</head>
<body>
<div id="container"></div>
<script src="http://cdn.bootcss.com/babel-core/5.8.34/browser.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-with-addons.js"></script>
<script src="http://cdn.bootcss.com/react/0.14.7/react-dom.js"></script>
<script src="http://cdn.bootcss.com/marked/0.3.5/marked.js"></script>
<script type="text/babel">
var mountNode = document.getElementById('container');

var MarkdownEditor = React.createClass({
getInitialState: function() {
return {value: 'Type some *markdown* here!'};
},
handleChange: function() {
this.setState({value: this.refs.textarea.value});
},
rawMarkup: function() {
return { __html: marked(this.state.value, {sanitize: true}) };
},
render: function() {
return (
<div className="MarkdownEditor">
<h3>Input</h3>
<textarea
onChange={this.handleChange}
ref="textarea"
defaultValue={this.state.value} />
<h3>Output</h3>
<div
className="content"
dangerouslySetInnerHTML={this.rawMarkup()}
/>
</div>
);
}
});

ReactDOM.render(<MarkdownEditor />, mountNode);
</script>

</body>
</html>

關鍵點:

  1. 可以使用自定義函數用作過濾器,如這裡引入的marked.js裏的marked()
  2. React中的設置HTML的APIdangerouslySetInnerHTML,返回含有__html屬性的object即可
  3. 使用refs拿到DOM?思考一下是不是吧~

    額外的Tip:React還沒有1.0.0,很多都經常變化,refs在以前不是這麼拿到,哭死我們這些前端小白了~

結語

前端之路還很長,React大法好啊~

2016年廣州前端面試之旅

2015年過去的好快,在荔枝FM帶了好像沒有多久的時間,其實也不算短,將近一年了。
我在知乎上改了簽名:“2015过去了,2016又会怎么样……”,其實對2016年還是蠻忐忑的,因為有計畫想要換一份新的工作,但是覺得自己水平還不夠強。
說說在荔枝FM的一年吧!想起來還是2015年3月的時候,那是我在知乎上搜了一下“互聯網 廣州”,然後看到了一個問題“广州有哪些比较酷的互联网公司?”,注意到荔枝FM這家公司。
後來我就看了下荔枝FM的官網,找到了前端的崗位,但是那個崗位要求好高,要3年工作經驗。那時的荔枝FM貌似並不招應屆生,不過我抱著試一試的心態投了簡歷。沒想的是,要不到一天電話聯繫我,說那邊的老大對我比較感興趣,問我要不要去面試。然後我就很冷靜的說好,其實內心很激動╰( ̄▽ ̄)╮
一切還是蠻順利的,我進了荔枝FM,做了一名前端碼農。那時公司還不是很多人,我進去的時候也就五六十人,前端也就導師和我在做。雖然天天被催著做移動端的頁面,還有一些專題頁,還要寫後端,沒辦法人少~但是那時真的好快樂,幸福感爆表。現在進荔枝FM的小夥伴應該很難體會在增園那一段的時間。在創業公司有不少感觸,好的地方是你可以接觸各式各樣的工作,除了做前端,我偶爾也參與設計,例如:開屏圖、banner,參與和客戶端的同事共同做內置瀏覽器的接口,前後端一手包,瞭解很多營銷的技巧,產品思想,等等……我在這一年成長的很快。不好的地方也很多,你想把很多東西做到極致的比較難,即使你想做。一方面是很多時候你是在對付業務,另一方面是我進去的時候前端可以說是沒有基建的,很多東西都要自己去Initial building,所以沒有做到極致的條件。例如說是使用webpack、gulp和後端融合,CDN加速,前後端分離,DNS預取,React和Vue預研應用。其中有一回蠻有挫敗感的,我花了接近兩個星期做了前端分享準備,做PPT,寫逐字稿,寫Demo,分享一個關於“Web Component”的主題。但是由於大部分同事還是做後端的(在很多後端眼裏,前端都是玩具的說>﹏<),所以反映平平。
言歸正傳,說說2016吧!最近面了很多互聯網公司,大大小小各式各樣的都有,其實蠻累的,現在也拿到了心儀的offer了,就和大家分享一下在廣州前端面試的一些感悟~
廣州算是沒什麼大的互聯網公司,騰訊在深圳,阿里在杭州,百度在北京。廣州呢,也就是WXG、MIG、阿里UC、唯品會、YY、網易一類,除了唯品會和YY,在這裡的大公司都是分部。面試的感覺是廣州的大公司其實都比較中規中矩,而小公司都是比較跳。為什麼這麼說呢?因為大公司的分部一般來說會思維比較體系化了,更多的是穩重求進。舉個例子,MIG的前端部分並沒有什麼硬性的技術選型,你想用React就用,想用Vue就用,jQuery都ok,用什麼構建工具都可以,只要能完成業務。小公司(不計其數)的想法比較跳,例如用比較潮的nodejs、webpack、python、go等等,但是經常會在技術選型上漂浮不定,用Express發現不夠完美換成koa的不少,糾結用React、Vue還是Angular,用了Grunt又換Gulp。其實我的看法是,不要糾結框架、工具鏈~
當然你會問我最後去哪裡了?我想是天貓前端。天貓的前端算是業務核心,在那裡可以有一個很好的團隊,很牛很棒的上司。天貓的技術選型(React+babel+gulp)也很吸引熱愛前端的人。只是有一點,我很捨不得廣州,這裡有滿滿的回憶,給我幸福感和歸屬感。我怕去了杭州會不習慣,然而為了熱愛的前端還是值得的~
最後,「Stay hungry. Stay foolish.」

Sublime Text 3 (Build 3103) 注册码

1
—– BEGIN LICENSE —–
Michael Barnes
Single User License
EA7E-821385
8A353C41 872A0D5C DF9B2950 AFF6F667
C458EA6D 8EA3C286 98D1D650 131A97AB
AA919AEC EF20E143 B361B1E7 4C8B7F04
B085E65E 2F5F5360 8489D422 FB8FC1AA
93F6323C FD7F7544 3F39C318 D95E6480
FCCC7561 8A4A1741 68FA4223 ADCEDE07
200C25BE DBBC4855 C4CFB774 C5EC138C
0FEC1CEF D9DCECEC D3A5DAD1 01316C36
—— END LICENSE ——
1
—– BEGIN LICENSE —–
Nicolas Hennion
Single User License
EA7E-866075
8A01AA83 1D668D24 4484AEBC 3B04512C
827B0DE5 69E9B07A A39ACCC0 F95F5410
729D5639 4C37CECB B2522FB3 8D37FDC1
72899363 BBA441AC A5F47F08 6CD3B3FE
CEFB3783 B2E1BA96 71AAF7B4 AFB61B1D
0CC513E7 52FF2333 9F726D2C CDE53B4A
810C0D4F E1F419A3 CDA0832B 8440565A
35BF00F6 4CA9F869 ED10E245 469C233E
—— END LICENSE ——
1
—– BEGIN LICENSE —–
Anthony Sansone
Single User License
EA7E-878563
28B9A648 42B99D8A F2E3E9E0 16DE076E
E218B3DC F3606379 C33C1526 E8B58964
B2CB3F63 BDF901BE D31424D2 082891B5
F7058694 55FA46D8 EFC11878 0868F093
B17CAFE7 63A78881 86B78E38 0F146238
BAE22DBB D4EC71A1 0EC2E701 C7F9C648
5CF29CA3 1CB14285 19A46991 E9A98676
14FD4777 2D8A0AB6 A444EE0D CA009B54
—— END LICENSE ——
1
—– BEGIN LICENSE —–
Alexey Plutalov
Single User License
EA7E-860776
3DC19CC1 134CDF23 504DC871 2DE5CE55
585DC8A6 253BB0D9 637C87A2 D8D0BA85
AAE574AD BA7D6DA9 2B9773F2 324C5DEF
17830A4E FBCF9D1D 182406E9 F883EA87
E585BBA1 2538C270 E2E857C2 194283CA
7234FF9E D0392F93 1D16E021 F1914917
63909E12 203C0169 3F08FFC8 86D06EA8
73DDAEF0 AC559F30 A6A67947 B60104C6
—— END LICENSE ——

Ubuntu安装php

  1. 安装apt源管理工具、添加nginx和php的安装源

    1
    2
    3
    apt-get install python-software-properties
    add-apt-repository ppa:nginx/stable
    add-apt-repository ppa:ondrej/php5
  2. 更新系统软件

    1
    apt-get update
  3. 安装mysql

    1
    apt-get install mysql-server mysql-client
  4. 安装php及对mysql的支持

    1
    apt-get install php5-fpm php5-mysql
  5. 根据实际需要,选择性的安装php的各类功能模块

    1
    2
    3
    4
    5
    6
    apt-get install php-pear php5-dev php5-curl
    apt-get install php5-gd php5-intl php5-imagick
    apt-get install php5-imap php5-mcrypt php5-memcache
    apt-get install php5-ming php5-ps php5-pspell
    apt-get install php5-recode php5-snmp php5-sqlite
    apt-get install php5-tidy php5-xmlrpc php5-xsl
  6. 安装nginx

    1
    apt-get install nginx
  7. 修改nginx默认站点配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    vim /etc/nginx/sites-available/default

    server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    server_name server_domain_name_or_IP;

    location / {
    try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root /usr/share/nginx/html;
    }

    location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    }
    }

Ubuntu安裝java8

  1. 添加ppa

    1
    sudo add-apt-repository ppa:webupd8team/java
  2. 更新系統

    1
    sudo apt-get update
  3. 安裝java8

    1
    sudo apt-get install oracle-java8-installer
  4. 檢測是否成功

    1
    java -version

結果如下

1
2
3
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

  1. 設置環境變量

    1
    sudo apt-get install oracle-java8-set-default
  2. 版本切換

    1
    sudo update-java-alternatives -s java-8-oracle

Play Framework項目初始化

安裝Activator

先下載Activator
解壓到D:\Program Files\activator-1.3.2
D:\Program Files\activator-1.3.2加到環境變量Path中
在你的項目目錄中執行以下命令,驗證是否安裝成功

1
activator -help

創建Play項目

1
2
3
activator new demo play-java
cd demo
activator

安裝Eclipse插件

Scala IDE
在Eclipse中Install New Software增加宰割Update Site,記得安裝Play Support

創建Eclipse項目

1
eclipse with-source=true

跑起來看看

1
run

在瀏覽器中打開http://localhost:9000,項目就跑起來了╰( ̄▽ ̄)╮

工作心得

寫這篇文章的初衷

想想在荔枝FM工作接近2個月了,一直沒能好好總結是一個很大的問題,因此今天就來寫一些東西來回顧一下過去的工作。

工作列表

  • 荔枝達人HTML5遊戲
  • 運營後臺·標記播客庫
  • 微信錄音
  • 錄音指南HTML5
  • 程壁線下文藝店HTML5
  • 主播資料收集頁HTML5
  • Young榜HTML5
  • 推廣後臺

工作中用到的東西

荔枝達人

HTML5遊戲使用egret(白鷺)引擎,這個引擎是使用TypeScript來寫。TypeScript感覺挺好的,顯式類型並且接近ES6規範,但是有一點比較坑的是,對於第三方庫的引入不是很理想,表面而言就是引用的第三方庫後綴為d.ts

有時間就謝謝TypeScript的一些東西和大家分享。

運營後臺

運營後臺使用的是公司自己編寫的Java後端框架,一開始我一直在熟悉這個框架,覺得很不適用,但是當我仔仔細細的看過後又挺欽佩前人的智慧。在熟悉完項目之後就開始編寫自己的功能模塊了。這個項目是使用自己定義的MVC框架,定義了一些Controller規範,已經對應View的規則,使用的持久化框架是MyBatis。Model對MyBatis進行封裝,可在選擇在自動事務和自行事務處理,默認為自動事務。總體而言,在寫完一個功能模塊並使之上線算是一次完整的框架“遊覽”。

順便提一個,部署這一塊也是挺有趣的。公司在安全方面挺注重的,因此每個人要將項目部署上去都必須經過跳板機。感謝公司“萬能”的運維大大,在跳板機上有對應掛載的目錄,因此部署也不是太麻煩。我使用的是XShell,對應的上傳下載命令也就是rzsz

po一下最近學習的運維知識(果然Linux課都白上了,只學到ls和sudo)
以下出於安全考慮,全部command都隱去敏感字符

1
ssh -p port host@192.168.1.1
1
mysql -uname -p -h 192.168.1.1 -P port database_name

順便po一下最近自學的mysql權限處理

1
2
service mysql stop
/usr/bin/mysqld_safe --skip-grant-tables &
1
2
3
4
5
6
7
8
9
10
11
use mysql;

INSERT INTO user VALUES ('localhost','root',password(''),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','','0','0','0','0','','');

INSERT INTO user VALUES ('127.0.0.1','root',password(''),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','','0','0','0','0','','');

INSERT INTO user VALUES ('::1','root',password(''),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','','0','0','0','0','','');

INSERT INTO user VALUES ('%','root',password(''),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','','0','0','0','0','','');

flush privileges;

1
2
3
4
5
ps aux | grep 'mysql'
kill -9 mysqld-pid
service mysql start
vim /etc/mysql/my.cnf
bind-address = 127.0.0.1

上面這些有的是為了遠程訪問Mysql,看不懂就算了,關於運維以後再補。

微信錄音

做微信录音讓我知道了Redis可以用來做服務,這種方式真的很“潮”,這個項目是使用Play Framework作為後端的。
下面講講這個Play Framework

Play FrameworkRuby on Rails非常相似,算是Java的Rails,編寫東西相當敏捷,配置很靈活,缺點也有,模版引擎略坑。這個框架有很多配套的組件,Eclipse的Scala IDE,Play Support,sbt,activator,等等。一些實踐,怎麼編寫Annotation實現簡單權限,怎麼用less,怎麼打包部署,編寫reload腳本等等。發現好多東西要補,5555……

錄音指南

這是一個翻頁HTML5,因為是一個靜態的項目,而且比較獨立,所以這個項目用了很多前端的東西,列表如下:

  • yeoman
  • glup
  • webstorm
  • bower
  • browser-sync(這是個非常好的東西)
  • n多的gulp插件

項目部署在nginx下。

關於移動端head的較好處理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<head>
<meta charset="utf-8">
<title>Title</title>
<meta name="description" content="description">
<meta name="viewport" content="target-densitydpi=device-dpi, width=640px, user-scalable=no" />
<!-- 删除苹果默认的工具栏和菜单栏 -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- 设置苹果工具栏颜色 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<!-- 忽略页面中的数字识别为电话,忽略email识别 -->
<meta name="format-detection" content="telephone=no, email=no" />
<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized" content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- windows phone 点击无高光 -->
<meta name="msapplication-tap-highlight" content="no">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- 360强制全屏 -->
<meta name="360-fullscreen" content="true" />
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- 适应移动端end -->
<!-- Place favicon.ico in the root directory -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon.ico">
</head>

鎖定在640px就不用擔心什麼了,話說那些這麼寫的是要做什麼

1
<meta name="viewport" content="width=device-width,target-densitydpi=high-dpi,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

程壁線下文藝店 & 主播資料收集頁

這兩個差不多,都是HTML5表單,後端也是Play Framework(真的挺好用的框架),用了一下百度統計和騰訊分析,感覺不錯。

Young榜HTML5

這個任務拖了我一個多星期,本來預計兩三天結果,結果設計師和市場一直在糾結設計需求,不過要不是這樣也不會有一個好用的推廣後臺╮(╯▽╰)╭,
這個東西用了Swiper,很贊的觸摸滑動插件,對移動端支持很棒。

這個HTML5是可以配置修改的,只要在後臺設置好就能生成新的一期了,總體來說還ok。

推廣後臺

這個也能講一大堆,暫時不講了,休息休息~~