1. 程式人生 > >我的第一個上線H5頁面

我的第一個上線H5頁面

結果 ssa 方便 我沒 改變 round 必須 文章 書寫

我的第一個任務是做一個h5的拉新頁面

設計稿

技術分享圖片

功能說明

在貝貝的貝殼任務新增"聽兒歌贏獎勵",期望能拿到更多拉新資源;

  • 獎勵1,播放兒歌贏獎勵
  • 每天抓取昨日播放量最高的前6個專輯;
  • 用戶默認訪問時展示前3個,點擊換一換更換後3個;
  • 點擊後直接進入播放器,播放內容是專輯的第一個內容;
  • 點擊頁面上專輯位置,認為用戶進行了1次播放,後端加1貝殼;
  • 每個用戶每天最多加3個;
  • 獎勵2,下載早教寶送30貝殼
  • 點擊按鈕,跳轉下載地址,安卓直接下載,iOS跳轉到Appstore下載,下載成功+30貝殼;
  • 獎勵3,展示早教寶內的內容
  • 展示內容,點擊跳轉下載地址。

如果這只是一個屋限制的單張頁面,其實寫起來很容易的,用我以前所學的只是,不到半天的時間就可以寫出這樣一張頁面。但在公司就沒有這麽簡單。一個公司代碼量龐大,公司內部自己封裝了許多經常用的函數,而且app用戶量龐大,我們必須考慮到個方面的性能問題。

下面開始講代碼的問題

編輯器

公司開發大都用vscode編輯器,它和sublime很相似,但是它有更強大的功能

代碼結構

公司內部封裝好了,當需要新建一個頁面時,運行

npm run newpage party/activity

會自動給你生成一個文件夾,文件夾下面包括四個文件

技術分享圖片

xtpl:是xtemplate的縮寫,它是一種模板語言,和ejs類似。很多電商網站,如淘寶都使用這個模板語言。我們可以把列表渲染等拼接字符串丟到xtemplate裏面,這樣可以使我們的代碼看起來簡潔美觀。

less:less的好用之處在於讓我們的css和html一樣具有層級關系,讓我們的代碼給具有可讀性和可修改性。但要註意的是,層級嵌套不要太深,最多三級。因為瀏覽器讀取的時候是從最裏層向外找得。比如最裏層是p,那就會找到頁面中所有的p在找它的父級,很明顯這樣耗時。而我們又希望達到向html一樣的層級關系,我們可以用&。下面是代碼示例

.activity {
  width: 100%;
  letter-spacing: 2/@bs;
  font-size: 26/@bs;

  img {
    display: block;
    width: 100%;
  }
  &_music {
    margin-top: -10/@bs;
    padding: 6/@bs 40/@bs;
    height: 345/@bs;
    background-image: url(http://h0.hucdn.com/open/201804/5036d34bc97103eb_750x333.png);
    background-size: 100% 100%;
  }
}
    

最終“&_music”會被解析為“.activity_music”而不再是“.activity .music”

HTML

我們應該把html中需要和後端交互的一部分放在xtemplate中,然後通過js去將它添加到某個節點下

CSS

圖片小縫隙問題

因為我寫的是一張h5的拉新頁面,頁面的復用性不強,所以不需要點擊的部分都是直接通過截圖來實現的。

    <div class="reward1">
            <img src="http://h0.hucdn.com/open/201804/a092bae6fe513b30_750x335.png">
            <div class="activity_music">

            </div>
        </div>
        <div class="reward2">
            <img src="http://h0.hucdn.com/open/201804/269bd63c6bf51ee2_749x87.jpg">
            <img src="http://h0.hucdn.com/open/201804/76ad4d5de5f7aa8d_749x454.jpg" class="download" data-text=‘獎勵二‘>
        </div>
        <div class="reward3">
            <img src="http://h0.hucdn.com/open/201804/e832a8c05b217e81_750x102.jpg">
            <img class="download" src="http://h0.hucdn.com/open/201804/7439e89b1ef75c84_749x910.jpg" data-text=‘獎勵三‘>
        </div>
        <div class="reward4">
            <img src="http://h0.hucdn.com/open/201804/704e66e11bd5863f_750x494.png">
        </div>
    </div>

這樣會造成每個img後面都有一個小縫隙。這個小縫隙是怎麽產生的呢,可以參看張鑫旭的CSS深入理解vertical-align和line-height的基友關系

簡單的說,我把img放在div裏面

<div class="mask">
    <img src="http://h0.hucdn.com/open/201804/70999dd4e4598fe4_100x100.png">
</div>

在img後面會有一個很小的方塊以這樣的方式跟在它後面

技術分享圖片

要解決這個問題有這樣幾種方案

  • 最簡單的方法是將div和img之間的所有空格都去掉,向這樣寫

    <div class="mask"><img src="http://h0.hucdn.com/open/201804/70999dd4e4598fe4_100x100.png"></div>
    你可以這樣理解,行內元素將自己包裹起來,同一行內允許其他元素存在,所以我們在書寫html時div和img之間留了空隙,網頁上自然就也有縫隙。但是這種方法不推薦使用,因為這樣書寫不美觀,而且有的編輯器會自動為你添加縮進。
  • 將img的display設為block。因為這個原因是由img的display默認為inline-block造成的,所以我們將img的dispaly設為block讓它變成塊級元素就可以了。塊級元素自占整個一行,將img設為block就沒有元素可以和它共享這一行的位置了。
  • 將父級的font-size設置為0。一個空格相當與一個字,將font-size設為0了之後,這個字將不再占用空間。但使用這個方法的時候要註意,一定要在它的子集裏面重設font-size,不然真正的文字也變得看不見了。
  • 給img設置float:left。這樣做也不好,還需要去清除浮動。
  • 將vel-align設為bottom。這樣改變img與小方塊的對其方式其實小白塊還是存在,只是在縱向就看不出來了。

    div大小固定問題

我在做一個列表展示的時候,使用了flex讓它自適應為3塊,於是就沒有給它設置寬高了。但是我沒有考慮到的是有可能它的標題很長,這樣的話它就會自動將文字放到下面一排,這樣效果就很醜了。所以我需要設置它的寬高,並且overflow:hidden這樣即使它溢出也不會改變樣式了。

box-sizing

我在寫一段代碼的時候,背景是切的一個圖片,而我在width等於圖片大小後,有對div設置了padding。這樣我其實拉伸了背景圖片,雖然效果影響不大,但是代碼還是欠嚴謹。畢竟這幾px的距離,可能是UI構思了很久的結果

js

整體思路

  • 先引入一些插件
  • 新建一個xtemplate模板
  • Promise.polyfill()如果遊覽器不支持,幫你自動修補
  • 拿數據
  • 定義一些共用的函數
  • 建一個class
  • constructor中放一些共用的變量和需要執行的函數
  • 定義一些只有在class裏面在會用到的函數
  • 啟動頁面
    ```
    ‘use strict‘

import ‘./index.less‘
/eslint-disable no-unused-vars/
import sentry from ‘@base/sentry/zaojiaobao_m‘
import Promise from ‘es6-promise‘
import Xtemplate from ‘xtemplate/lib/runtime‘
import tmpl from ‘./index.xtpl‘
import { ajax, authenticationHandle } from ‘commons/js/tools.js‘
import Hybrid from ‘@base/simple_hybrid‘
import { sendLog, pageStart } from ‘libs/log/log2.js‘

const tpl = new Xtemplate(tmpl)

Promise.polyfill()
const getData = () => {
return ajax({
method: ‘GET‘,
query: {
method: ‘beibei.education.weal.reward.list‘
}
})
}

class Page {
constructor() {
Hybrid(‘customNavBarRightBtn‘).customNavBarRightBtn({
//默認隱藏右上角分享按鈕
hidden: true
})

}

}
pageStart()
new Page()

### 需要編寫的函數
#### 將音樂渲染到頁面中
因為音樂有多首,所以我采用xtemplate去渲染它們
    {{#each(albums)}}
  • 技術分享圖片 技術分享圖片

    {{title}}

  • {{/each}}
今天已收聽 {{listen_count}}首,獲得 {{get_shell_count}}個貝殼
這裏需要註意的是,我用到了data-id和data-target這些屬性,這是為了在js中我更方便去取到需要的數據
js部分

getData()
.then(res => {
this.res = res
this.albums = [res.albums.slice(0, 3), res.albums.slice(3, 6)]
this.res.albums = this.albums[0]
this.$music.html(tpl.render(this.res))
})
.catch(err => {
popup.note(err.message || err.err_msg || JSON.stringify(err))
})

這段函數放到class的constructor裏面。這裏用到了promise的異步請求,將請求成功的操作放在then裏面,報錯放在catch裏面。catch幾種報錯是為了記錄報錯的設備。

因為一共有六條數據,但是頁面只顯示三條數據,如果我將六條數據全交給模板,會造成樣式混亂。而且因為換一換需要的是前三條數據和後三條數據的切換,所以我將數據切好放在一個數組中,為換一換做好準備
#### 點擊換一換切換音樂

let _this = this
this.$music.on(‘click‘, ‘.changMusic‘, function() {
sendLog({
type: ‘click‘,
params: {
block_name: ‘點擊換一換‘
}
})
if (_this.res.albums === _this.albums[0]) {
_this.res.albums = _this.albums[1]
} else {
_this.res.albums = _this.albums[0]
}
_this.$music.html(tpl.render(_this.res))
})

這裏的思路是判斷當前狀態,如果是前三個就切換到後三個

sendLog是一個已經封裝好了的函數,通過這個記錄用戶的動作,方便運營對數據進行分析。
#### 點擊獎勵二或三跳到下載頁面

this.$activity.on(‘click‘, ‘.download‘, function() {
let text = $(this).attr(‘data-text‘)
sendLog({
type: ‘click‘,
params: {
block_name: ‘點擊領取聰明豆下載‘,
text: decodeURIComponent(text)
}
})
authenticationHandle(() => {
ajax({
method: ‘POST‘,
query: {
method: ‘beibei.education.download.reward.check‘
}
})
download()
})
})
```
這一部分的邏輯就是點擊的時候跳到下載,但是要登錄之後才可以下載。
authenticationHandle()是封裝好的登錄函數,download是封裝好的下載函數。

談一談this

見我的另一篇文章this的指向和用法

完整代碼https://github.com/hyz1997/beibei-edu-activty

我的第一個上線H5頁面