1
本文作者: 張丹 | 2017-01-13 16:12 | 專題:雷峰網(wǎng)公開課 |
1月9日,微信小程序正式上線,互聯(lián)網(wǎng)迎來了一次狂歡。
張小龍在上個月的公開演講中表示,“小程序是一種比現(xiàn)有所有 App 更加靈活,更加唾手可得的一種形態(tài),并將無處不在。”作為微信的一種新形態(tài),小程序不僅擴(kuò)大了微信的生態(tài),也被看作是移動互聯(lián)網(wǎng)的“革命者”。
任何文字解析都不如視頻直播直觀。
本次硬創(chuàng)公開課雷鋒網(wǎng)請到了「開眼」視頻的技術(shù)負(fù)責(zé)人為大家直播演示講解如何開發(fā)一款視頻微信小程序?!搁_眼」視頻是一款短視頻日報應(yīng)用。由「開眼」視頻團(tuán)隊制作微信小程序「開眼Eyepetizer」,作為為數(shù)不多的第一批上線的視頻類小程序,受到了許多開發(fā)者的關(guān)注。
嘉賓介紹:
楊凱,「開眼」視頻團(tuán)隊技術(shù)負(fù)責(zé)人。
曾供職于 360,是 360 手機(jī)桌面創(chuàng)始團(tuán)隊成員之一,由他參與研發(fā)的該款桌面在國內(nèi)第三方桌面市場很長時間排名第一。2014 年加入豌豆莢,任豌豆莢 Tech Lead,負(fù)責(zé)豌豆莢主程序開發(fā),主要參與網(wǎng)絡(luò)庫優(yōu)化,UI 性能調(diào)優(yōu),通過代理緩存多媒體 web 頁等工作。后加入「開眼」視頻團(tuán)隊,作為技術(shù)負(fù)責(zé)人,負(fù)責(zé)技術(shù)開發(fā)、迭代工作。
下文為雷鋒網(wǎng)整理的本次公開課直播分享中的要點。課后陳凱老師還分享了本次課程中完成的 demo,關(guān)注雷鋒網(wǎng)「唯物 」公眾號(ID:okweiwu),回復(fù)「 小程序」即可獲取鏈接。
今天主要講一下微信小程序的開發(fā),希望通過直播開發(fā)一個「開眼」視頻的小程序,幫大家了解微信小程序的開發(fā)步驟、流程以及基本 API 的使用,內(nèi)容主要包括以下幾個方面:
開發(fā)一個可滾動列表,在這個列表的制作中,我們會熟悉微信小程序數(shù)據(jù)綁定的方法,以及怎么樣發(fā)起一個網(wǎng)絡(luò)請求;
處理點擊事件,通過這一操作了解微信是怎樣做事件綁定的;
在列表的指定位置,展現(xiàn)一個視頻播放器,通過這一操作了解微信小程序給我們的視頻標(biāo)簽是怎樣使用的;
將頁面分享給好友,在好友對話里可以看到制作的微信小程序。
大家可以看到「開眼」視頻小程序就是一個簡單的列表,列表中的每一個畫面其實都是一個可以點開播放的視頻。進(jìn)一步分析可以得知,在我們看到的每一個視頻封面圖上有一個 icon,圖下面是這個視頻的文字介紹,標(biāo)題以及分類。繼續(xù)向下拉會發(fā)現(xiàn),有多少視頻,就會顯示多個元素,并且是刷新不到頭的。當(dāng)我們點擊一個視頻封面或播放按鈕 icon 時,視頻會開始播放,接著點擊播放第二視頻時,第一個視頻就會自動停止播放,以上就是我們這堂課想要完成的事情。
|步驟一:開發(fā)一個可滾動列表
由于時間關(guān)系,本次直播不會從零開始做這款小程序,會直接從微信的 demo (小程序組件)中開始操作。
這是微信小程序官方給出的一個 demo,可以看到有兩個 tab,今天的操作主要是在第二個 tab 的右邊再添加一個 tab,在第三個 tab 中實現(xiàn)一個跟「開眼」視頻小程序一樣的功能。
可以看到 pages 列表內(nèi)容非常多,其內(nèi)容主要是定義或聲明一下在這個小程序中會用到一些界面。windows 花括號里面的一些選項是幫你定義 tool bar 上的顏色和信息,可以在這個頁面看到demo 中 toolbar 的顏色就在這里設(shè)置的。
在 tab bar 里新加一個“開眼視頻”文件夾,配置地址是剛剛寫好的,抄過來就好,配制完成可以看到左邊的頁面已經(jīng)出來了,雖然沒有內(nèi)容,但第三個 tab 的框架已經(jīng)完成了。接下來是繼續(xù)開發(fā)這個 tab,我一般會直接從之前寫好的代碼里復(fù)制過來,然后進(jìn)行一些簡單的修改,演示一下變化過程。
注意要把相關(guān)文件名也改成“開眼視頻”,否則會出現(xiàn)找不到布局文件的情況發(fā)生。
文件夾名稱改完后,可以看到剛在第三個 tab 里添加的內(nèi)容,已經(jīng)可以顯示出來了,這是一個微信小程序官方 audio 的頁面,還需要對這個頁面進(jìn)行一些改動。
首先寫一下這個頁面的布局文件,把沒有用的布局文件刪掉,在最上層定義一個 view,進(jìn)行最外層的展示,然后會加一個 image 標(biāo)簽,這個標(biāo)簽主要的功能是展示剛才看到的 cover 圖(由于時間關(guān)系,直播時省略了敲代碼步驟,直接從之前的文件中拷貝)。
解釋一下拷過來的這幾行代碼。第一代碼是 WX : for,前面 WX 是微信的簡稱,后面的 for 是說,它會在你的 JS 文件里找到一個名字叫 videos 的變量,該變量是一個數(shù)組,image 這個便簽會重復(fù)多次,直到和 videos 數(shù)組長度一致。
后面 for-item 標(biāo)簽是指,每一個 image 標(biāo)簽可以通過 video 變量名拿到和它綁定在一起的視頻數(shù)據(jù),例如下面 video.coverForFeed 就是把當(dāng)前綁定的視頻數(shù)據(jù)中 coverForFeed 字段賦值給 image 的 src。
接下來看下 GS 的寫法,先定義一個 videos,也就是剛剛在布局文件里聲明需要的,這個 videos 會在 onload 里賦值。解釋一下 onload 這個方法:頁面被加載的時候,onload 會被調(diào)用。在微信小程序官方開發(fā)文檔中也可以看到這個方法的相關(guān)聲明,其中:
onload 是頁面被加載;
onready 是第一次渲染完畢;
onshow 是監(jiān)聽事件顯示;
onhide 是監(jiān)聽頁面被隱藏。
如果有前端開發(fā)經(jīng)驗的話,可以看到跟 window 的很多頁面很像.最常用的是 onload,再仔細(xì)看一下這個方法的使用,在這個地方會嘗試調(diào)用一個叫 load 的方法,并且把“我們自己”傳進(jìn)去,再傳一個options。解釋一下 options,舉個簡單的例子,如果想調(diào)一個這樣的配置,可以看到它的 url=page/item/item,后面會帶一個參數(shù),參數(shù)名叫 id 值等于 1,這個方法是在調(diào)用者那邊使用的,被調(diào)用者也就是被喚起的頁面怎么樣讀到這個 id 等于 1 的參數(shù)呢?是通過 const id = options.id 這個代碼,options 相當(dāng)于頁面間傳遞參數(shù)傳遞的一個工具。
再看下 load 的方法,一行一行的來看,第一行 pages 和 options 是兩個傳參,第二行 wx.ewqiest 是發(fā)送一個 API 請求,注意,小程序官方文檔里的對 wx.ewqiest 的定義是發(fā)送一個 HTTPS 請求,現(xiàn)在是本地操作,如果是線上環(huán)境的話,一定要寫成 HTTPS,否則會被攔截。完整示例寫法如下:
url 是請求的地址;
data 是 url 里的參數(shù),也就是我們傳進(jìn)去的參數(shù);
header 是我們發(fā)送 HTTPS 請求的時候所帶的 header;
success 當(dāng)發(fā)送成功時,這個方法會被回掉;
fail 當(dāng)請求失敗時,會回調(diào)這個方法,通知你失敗的原因。
再回到開發(fā)頁面,video:videoData 是說把本地變量變?yōu)榕渲玫膮?shù),要注意的是微信小程序和 Vue 不同,小程序的數(shù)據(jù)不是雙向綁定的,或者說不是默認(rèn)雙向綁定的,如果數(shù)據(jù)或數(shù)據(jù)結(jié)構(gòu)發(fā)生了改變,想通知到 video 層級上,讓 video 去刷新,必須要通過 page 中的 setdata 來實現(xiàn)。也就是說必須要這樣寫, videos 才會生效(video=videoData 的形式不不會生效)。
現(xiàn)在已經(jīng)把簡單的列表寫好了,回到微信小程序的開發(fā)列表里可以看到,已經(jīng)顯示出了我們想要的效果,我們請求到了 6 個視頻,界面上顯示了六個 cover 圖。微信會對 image 標(biāo)簽有默認(rèn)的高和寬(240*320 像素),所以需要對圖片進(jìn)行微調(diào)。
接著寫 css,微信的 css 語法和標(biāo)準(zhǔn)的 css 語法幾乎沒有區(qū)別,只是有一些子集不支持,這些在微信的開發(fā)文檔里也有寫,但是我們一般用到的都有。需要額外講下 rpx,這是微信小程序里自己定義的一個屬性。這個屬性的定義是說它認(rèn)為所有屏幕的寬都是 750 個 rps,也就是說,你拿到一臺 iphone 5 和一臺 iphone 6S,它的寬都是750 rpx。
但是會反過來算一個像素等于多少 rpx,在 iphone5 里,假如說一個像素等于一個 rpx的話,在 iphone 6 里,兩個像素等于一個 rpx。這樣做的好處是降低了 UI 的適配成本。
到這里本堂課的第一個目標(biāo)已經(jīng)完成,已經(jīng)開發(fā)完成了一個可滾動的列表,并熟悉了數(shù)據(jù)綁定和網(wǎng)絡(luò)請求。
|步驟二:處理點擊事件
接下來要處理一個點擊事件,點擊事件觸發(fā)之后,會在圖片原來的位置展示一個視頻播放器,并且播放圖片所代表的視頻。
先看一下微信小程序定義的的事件綁定過程是怎樣的:
在組件中綁定一個事件處理函數(shù),如 bindtap,這個用戶在點擊組件的時候,就會出發(fā)到這個 video 的 bindtap。
高亮的這幾行意思是我把一個函數(shù) tapname 綁在 video 標(biāo)簽的點擊上。也就是說當(dāng)前這個 video 標(biāo)簽被點擊時,系統(tǒng)會調(diào)用名字為 tapname 的方法,并且把當(dāng)前 video 的一些參數(shù)傳到這個 tapname 函數(shù)里。
接下來在項目里定義一個綁定,把 image 的點擊事件綁定在一個 onTap 的方法上。接下來要在 JS 里實現(xiàn)這個 onTap 的方法。
在 JS 里 onload 下面,重起一行接著寫 onTap:function (element),微信小程序官方文檔中對 element 的定義中包涵了幾個屬性:
type (事件類型);
timeStamp(事件生成時的時間戳)
target(觸發(fā)事件組件的一些屬性值結(jié)合)
currentTarget(當(dāng)前時間的一些屬性值集合)
接下來要實現(xiàn)一個方法叫 tap,它需要兩個傳參,第一個是 page,第二個是 element。page 就是 this,element 就是剛剛定義的 element,傳進(jìn)來后可以看到這個方法就被調(diào)用了。打一個 log 可以看到以下結(jié)果。
每點一次,下面都會出現(xiàn)一個 tap,也就是說已經(jīng)成功的把 video 上的事件傳遞到了 JS 的處理函數(shù)中。
第一段代碼中的 element 就是剛剛傳過來的被點擊元素,currenttarget 是當(dāng)前被點擊的目標(biāo)… 重點講下videoUrl,videoUrl 是剛在開發(fā)中定義的一個內(nèi)容,不是系統(tǒng)自帶的,看下它是從哪里來的
data-video-id 的意思是把當(dāng)前視頻 id 附給 image 標(biāo)簽,作為這個 image 標(biāo)簽上的屬性,當(dāng)點擊一個 image 標(biāo)簽是,JS 可以從傳入的 element 中讀到這個值。
因為列表里有 6 個標(biāo)簽,所以必須要知道當(dāng)前點擊的標(biāo)簽是什么,以及當(dāng)前被點擊的標(biāo)簽上綁定的 video 數(shù)據(jù),來決定后面需要播哪一個視頻。
id 我們用不到,先刪去。上面的寫法是 -video-url 這個地方寫成 videoUrl 略有不同。原因是微信小程序會幫開發(fā)者們做一件事情,把 data 和后面的橫線去掉,然后自動駝峰。
上面這句話的意思是從被點擊的 element 中拿到當(dāng)前標(biāo)簽綁定的 video 的播放 url 是什么。可能很多做前端的同學(xué)心里會有疑問,為什么要費這么大勁去拿,而不通過一些其它的手段。因為微信小程序廢除了 document,以及 window 的很多方法,目的是讓小程序變成純數(shù)據(jù)驅(qū)動的編程思想,也就是說所有的事件和所有的數(shù)據(jù),一定是以事件或者是消息這樣的方式來傳遞的,開發(fā)者沒有辦法主動的去拿到當(dāng)前顯示的 video。
舉一個簡單的例子,如果在頁面加載完后,設(shè)一個 timer 定時器,每五秒中告知當(dāng)前列表中展示的第一個元素是什么,這個在小程序里做不到。因為沒有辦法主動拿到當(dāng)前列表這個元素,也就沒辦法拿到列表上展示的內(nèi)容,只有一種辦法,用戶手動觸發(fā)了一個事件時,開發(fā)者才可能拿到這個事件相關(guān)的(并不是所有的)一些信息。
為了取到當(dāng)前被點擊的這個 item 上面綁定的 video 的播放地址,要通過這種方式來實現(xiàn),而不能通過其它的方式來實現(xiàn),這個確實有點繞。
這個思想在微信小程序里可以說是最重要的思想,也就是 DOM 模型幾乎完全不能用。這個可能給很多前端開發(fā)帶來非常大的困擾。
|步驟三:在列表指定位置展示視頻播放器
接著來看一下,現(xiàn)在還要做另外一件事,要在界面里加一個 video 標(biāo)簽,id 叫 video,class 叫 video,這樣寫主要是為了一會兒 CSS 綁定用。
后面它的 style 寫法,第一是 display,為什么用這個屬性,據(jù)我個人的經(jīng)驗,在微信里如果想隱藏一個 video 標(biāo)簽,只有這一種方法可以隱藏,也就是說 display 屬性設(shè)成 none,才可以把 video 隱藏,visibility hidden 方式都不行。
top 就是說這個視頻標(biāo)簽在列表中距離頂端的位置,所有帶兩層大括號的東西都是引用到 JS 里的變量,兩個變量一個是 covertop,一個是 videoDisply,src 是 currentUrL,就是說 video 播放地址是什么,這也是第三個變量。
對上面三個變量做個定義:
videoDisplay 是 none,默認(rèn)隱藏 video 標(biāo)簽;
covertop 是 video 標(biāo)簽?zāi)J(rèn)頂部,隱藏在那里都可以;
currentUrl 開始時為空,也就是說在開始時,視頻播放器里是沒有地址的。
再來看一下 tap 事件,直接復(fù)制過來三行。前面 page.setdata 是給下面的 data 進(jìn)行一種更新,這是一種特殊的復(fù)制方法。offsettop 這個屬性會告訴你當(dāng)前被點擊的元素,相對它的父節(jié)點向下挪了多少位置 。currentUrl,就是剛才拿到的 url。后面的 videodisply:block,是指現(xiàn)在可以顯示出視頻元素了。
試一下,頁面刷新了,說明更改生效了??梢钥吹揭曨l播放器已經(jīng)出現(xiàn)了,而且進(jìn)度條已經(jīng)顯示出時間了,但是還沒有開始播。下一步想辦法讓它開始播放。
先看一下微信小程序的的定義:
微信定義一個方法叫 creatVideoContext,意思是說在傳入一個 videoid 時,它會把當(dāng)前 videoid 的 video 元素與系統(tǒng)的播放器進(jìn)行綁定,也就是完成這個操作后的你添加的這個元素就可以播了。
微信官方共提供了play、pause、seek、sendDanmu 四種方法。
看下代碼,可以看到 creatVideoContext,傳入的參數(shù)叫video,就是剛才說布局文件里定義的一個 id 等于 video。
可以發(fā)現(xiàn)視頻已經(jīng)開始播了,劃動一下列表,視頻跟著這個列表在走,第二個視頻顯示出來后,并沒有播放。
這是我自己發(fā)現(xiàn)的微信小程序里 bug,點擊第二個視頻時不能自動播放,手動點控制條的時候有可能觸發(fā)播放,這是小程序系統(tǒng)的 bug。但有方法可以繞過:在原來的方法上加兩句話,就是設(shè)一個 timeout,也就是將這個事件延遲一段時間再出發(fā),點擊事件結(jié)束之后 500 毫秒再去觸發(fā)視頻的播放。
微信官方推薦用自帶的 IDE 來做開發(fā)。但是我平時還會做其它平臺的開發(fā),所以會比較傾向統(tǒng)一用 intellij,寫好代碼后只在微信小程序里做調(diào)試。繞過 bug 后可以看到滑視頻隨著列表滾動可以自動播放了。這樣我們基本上完成第二個目標(biāo),在列表中播放視頻,而且在滾動列表時只有一個視頻在播放。
|步驟四:將頁面分享給好友
在微信小程序官方文檔的最后,可以看到有一個關(guān)于 onShareAppMessage 的說明,意思是如果你在頁面里定義了這個函數(shù),這個函數(shù)叫 onShareAppMessage,右上角會出現(xiàn)分享按鈕。
可以看到,不定義這個函數(shù)時,點擊右上角會出現(xiàn)“當(dāng)前頁面未設(shè)置分享”的提示。
接下來寫這個代碼,直接把官方文檔抄過來即可,要注意,設(shè)置頁面元素時,一定要在 page 后的括號中寫,也就是說,一定要在 page 頁面里設(shè)置有關(guān)這個頁面的系統(tǒng)回調(diào)。保存后回到 IDE,點擊右上角,會出現(xiàn)分享按鈕,可以自定義分享標(biāo)題與自定義分享描述。
看一下代碼也是這么寫的:自定義標(biāo)題、自定義描述、自定義 path。自定義 path 是最外層還有一個 APP.gaisen,里面定義了所有的頁面地址,把頁面地址可以寫過來后我們今天的任務(wù)就完成了。
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。