吳鍵成 周旭宇 陳怡芯
摘要:該文描述了利用高度遵循MVVM架構(gòu)的前端框架Vue Js并以前后端分離的方式開發(fā)一個(gè)網(wǎng)絡(luò)基礎(chǔ)課程在線教學(xué)平臺(tái)。在這個(gè)平臺(tái)中學(xué)生用戶可以通過圖文/視頻的方式學(xué)習(xí)課程、完成作業(yè)練習(xí)、在線提問、參與考試、在線觀看課件;教師用戶完全擁有學(xué)生用戶的功能并且能發(fā)布課程信息、發(fā)布作業(yè)/考試、上傳課件/資源、查看學(xué)生考試情況等。該平臺(tái)結(jié)合了富文本、WebSocket、Canvas等技術(shù)呈現(xiàn)出一個(gè)功能豐富的在線教學(xué)平臺(tái),為類似需求的實(shí)現(xiàn)提供一種實(shí)現(xiàn)思路。
關(guān)鍵詞:MVVM;Web;Vue JS;Node JS;在線教學(xué)
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1009-3044(2020)05-0083-04
開放科學(xué)(資源服務(wù))標(biāo)識(shí)碼(OSID):
1 背景
隨著前端領(lǐng)域的高速發(fā)展、技術(shù)不斷更新迭代,越來越多的網(wǎng)站首選使用前后端分離的方式來進(jìn)行開發(fā),大大小小的前端框架也在前端生態(tài)中先后涌現(xiàn),其中華人尤雨溪的Vue JS框架在前端生態(tài)中知名度一直在提升,與Facebook的React、谷歌的Angular并稱為前端三大框架。Vue JS的架構(gòu)高度遵循MV-VM,其視圖層和數(shù)據(jù)模型層的分離的思想在前端的開發(fā)上帶來了很多便利。本文就在線教學(xué)平臺(tái)這一案例,闡述利用VueJS作為基本技術(shù)棧,對該在線教學(xué)平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)。
2 MVVM的理解
MVVM架構(gòu)分為三層:Model、View、ViewModel。Model層代表數(shù)據(jù)模型,數(shù)據(jù)的修改、操作邏輯就在這一層中定義;View代表視圖,負(fù)責(zé)把數(shù)據(jù)模型轉(zhuǎn)化為UI;ViewModel則是自動(dòng)地把Model、View兩層連接起來,使用者無須關(guān)心,可以把更多注意力放在Model-層上。MVVM架構(gòu)的這一特征使得開發(fā)者能更專注于業(yè)務(wù)邏輯的開發(fā),無須手動(dòng)操作DOM,代碼可讀性要強(qiáng)上不少,特別是在像大型項(xiàng)目這樣需求功能豐富的情景下,能節(jié)省開發(fā)者大量的精力,縮短開發(fā)周期,也減少了傳統(tǒng)前端開發(fā)因?yàn)镈OM操作頻繁所帶來意想不到的BUG。
3 技術(shù)選型
本項(xiàng)目在前端方面選用了并沒有完全遵循但高度遵循MVVM架構(gòu)的Vue JS(MVVM架構(gòu)不允許View層與Model層直接通信,對于某些情境下的前端組件化中父子組件的通信帶來了不便,Vue JS提供了ref屬性解決了該問題,但違背了MVVM架構(gòu)本身),Vue JS組件化的思想使得項(xiàng)目的部件、功能變得模塊化,更易讀、更容易維護(hù),很好地解決了傳統(tǒng)前端開發(fā)需要開發(fā)人員手動(dòng)書寫大量閉包來實(shí)現(xiàn)模塊化的狀況。
后端方面選用對高并發(fā)處理十分擅長的Node.JS,并與Koa.js框架相結(jié)合,Koa是Express框架的幕后原班人馬打造的基于Node.js平臺(tái)的下一代Web開發(fā)框架,支持ES7的Async/Await語法,能有效回避回調(diào)地獄和多層Promise嵌套使得代碼可讀性糟糕的問題。
數(shù)據(jù)庫選用了介于關(guān)系與非關(guān)系的MongoDB,MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫,旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案,它所支持的數(shù)據(jù)結(jié)構(gòu)是類似于json的bson,相比于關(guān)系數(shù)據(jù)庫如:MySQL,JSON式的存儲(chǔ)使其在業(yè)務(wù)上可拓展性要高上不少。
4 項(xiàng)目設(shè)計(jì)與實(shí)現(xiàn)
4.1 項(xiàng)目總覽
項(xiàng)目分為桌面PC端和移動(dòng)端,用戶類型分為兩種:教師用戶、學(xué)生用戶。平臺(tái)主要分為以下幾大模塊:課程模塊、資源模塊、答疑模塊、考試模塊、作業(yè)練習(xí)模塊。
4.2 用戶類型的識(shí)別
為了能給不同的用戶類型提供不一樣的權(quán)限控制,當(dāng)用戶登錄時(shí)都會(huì)傳人一個(gè)字段以標(biāo)識(shí)用戶類型,后端對該賬號(hào)的登錄認(rèn)證完成后會(huì)將該用戶類型連帶非敏感的用戶基本信息以及登錄狀態(tài)寫入前端cookie,而后前端每次向后端發(fā)起請求都會(huì)帶上該cookie,如此一來后端就能根據(jù)傳回的cookie獲知用戶類型以便做權(quán)限管理。至于在前端UI方面給不同類型的用戶顯示不一樣的交互頁面也無須專門給不同用戶準(zhǔn)備單獨(dú)不同的頁面組件,得益于視圖、數(shù)據(jù)模型分離的MVVM架構(gòu),利用在數(shù)據(jù)上對不同用戶類型的標(biāo)識(shí)作為條件,使用Vue的惰性條件渲染v-if指令即可渲染出供不同用戶類型使用的交互控件,達(dá)到同一個(gè)頁面組件給不同類型的用戶呈現(xiàn)響應(yīng)的交互界面的效果。
4.3 課程模塊
課程模塊需要實(shí)現(xiàn)富文本編輯課程章節(jié)內(nèi)容,可以本地上傳視頻或外鏈視頻,并能記錄用戶上一次觀看到的章節(jié)。富文本組件選用CKEditor,它擁有現(xiàn)代化又簡約美觀的UI,對xss(Cross-site scripting)攻擊也有一定的抵抗能力,但CKEditor的官方視頻導(dǎo)人模塊十分局限,不僅不支持本地視頻上傳,也不支持中國國內(nèi)常見視頻網(wǎng)站的外鏈。我們的解決方案是把官方的視頻組件提取出來進(jìn)行改造,使之能支持本地視頻的斷點(diǎn)續(xù)傳,并放棄使用vue模板創(chuàng)建HTML的方式,而是利用Vue中最接近編譯器的render渲染函數(shù)來渲染需要嵌入的外鏈視頻代碼,靈活且編程能力強(qiáng)的render函數(shù)能輕松應(yīng)對諸如優(yōu)酷、騰訊的外鏈視頻。把富文本中的視頻部分文本渲染成html模板展示到頁面有以下幾個(gè)步驟:
1)改造CKEditor的視頻導(dǎo)入插件中把視頻連接轉(zhuǎn)換成em-bed標(biāo)簽的邏輯(節(jié)選):
editor.config.define(,mediaEmbed ,{
providers:[
{
name:normal 7.
url: /^(.+Vmp4)/。
html: match=>f
returnf
+
、
)
}
},
{
name: 'youku',
url: /^vVyoukuVcomVv_showVid_(.+)Vhtml/,
html: match => {
return (
''
}
]
})分轉(zhuǎn)換相應(yīng)的 dom元素 :
slice(content) {
const normal_regex = /https? :\N.+Vmp4/gi;
const youku_regex = /https?:WvVyoukuVcomVv_showVid_(.+)VhtmVgi;
function gen_youku_template(url) {
return '
' allowfullscreen ' >' ;
const split = content.split(
/《figure class= "media" > kfigure class= "media">ygi
);
if (split.length === 0) {
return
}
split.forEach(p => {
return null;
}
let m;
if《m = youku_regex.exec(p》 !== null) {
return this.template.push(gen_youku_template (m[l l》;
}
if《m = p.match(normal_regex》 !== null) {
return this.template.push({
tag: 'videoPlayer',
data: {
props: [
options: {
language: 'zh_CN',
playbackRates: [0.7, 1.0, 1.5, 2.0],
fluid: true,
preload: ' auto ',
sources: [
{
type:,video/mp4r,
src: m[0]
)】),
】Ⅲ;
)
this.template.push(p);
”;
3)注冊無狀態(tài)函數(shù)式組件用作渲染組件:
components:{
videoPlayer,
CPCTemplate:{
functional: true,
props:{
el:f
type: Object,
required: true
¨,
render: function(createElement, content){
return createElement(
content.props.el.tag,
JSON.parse(JSON.stringify (content.props.el.data》
))))
4)渲染出富文本字符串中各個(gè)組成部分:
雖然在數(shù)據(jù)模型這一層次上有寫死html模板的邏輯,但依然體現(xiàn)著MVVM架構(gòu)中的數(shù)據(jù)驅(qū)動(dòng)視圖的思想,視圖層確實(shí)不需要關(guān)注模板的內(nèi)容,而是由數(shù)據(jù)模型層的邏輯去生成,視圖層依靠render函數(shù)和v-html指令就能正確渲染出我們所期望的內(nèi)容。
對于對用戶閱讀章節(jié)進(jìn)度的持久化概率我們采用了前端本地存儲(chǔ)方式中的locaIStorage方案,只需要在用戶進(jìn)入某一課程的某一章節(jié)頁面時(shí)(對應(yīng)Vue生命周期中的created或mount-ed)將信息寫入localStorage就達(dá)到了記錄當(dāng)前用戶閱讀進(jìn)度的目的,用戶無感知且無須發(fā)起請求。
4.4 資源模塊
資源模塊是課程資源的上傳、下載,包括PDF課件、課程視頻、軟件。PDF課件需要實(shí)現(xiàn)在線預(yù)覽、涂鴉功能,資源可模糊搜索。由于視頻可能會(huì)很大,以至于突破HTTP協(xié)議的消息體最大長度從而導(dǎo)致上傳失敗,為解決這個(gè)問題,我們將用戶上傳的視頻進(jìn)行了自動(dòng)分段,實(shí)現(xiàn)了斷點(diǎn)續(xù)傳,每一段的上傳都會(huì)帶上總段數(shù)、當(dāng)前段號(hào)等信息,當(dāng)最后一段上傳完畢后后端會(huì)把各段按順序拼接成一個(gè)完整文件并把分段文件刪除,把文件信息、地址存人數(shù)據(jù)庫后給前端返回文件地址;前端不僅可以計(jì)算出上傳進(jìn)度,還能在上傳完成后馬上獲取到文件URL。我們通過Canvas實(shí)現(xiàn)了PDF文件的在線預(yù)覽與涂鴉,把PDF文件的內(nèi)容按照分頁轉(zhuǎn)成圖片,繪制在Canvas中,把canvas封裝在組件中,通過props傳人參數(shù)控制當(dāng)前頁的顯示:
:src="src"
:page=”currentPage”
stvle=”background-color: #eee;”
@error=”pdfError
>
視圖是由數(shù)據(jù)驅(qū)動(dòng)的,通過vue的列表渲染就可以實(shí)現(xiàn)渲染pdf文件每一頁的縮略圖,監(jiān)聽縮略圖與“上一頁”“下一頁”控件的點(diǎn)擊事件,改變當(dāng)前頁面的數(shù)據(jù),vue即可根據(jù)被改變的數(shù)據(jù)去渲染視圖層(改變元素的樣式、pdf頁面的顯示):
:stvle=”(
transform: 、translateX(calc(-200-/o 術(shù) ${catalogueltemOffset-Page - iD)'
)”
@page-loaded=”pageLoaded(pageNumber)”
@error=”pdfError”
>
利用Canvas API、鼠標(biāo)onmousedown、onmousemove、on-mouseup事件可以實(shí)現(xiàn)畫圖功能,得益于Canvas API的支持,可以實(shí)現(xiàn)不同的筆刷粗細(xì)、筆刷顏色。模糊搜索功能則是使用動(dòng)態(tài)生成正則表達(dá)式的方式,使用非貪婪模式,過濾不匹配的結(jié)果實(shí)現(xiàn)的,該方式不僅在資源模塊中使用,在課程、答疑等模塊中皆有使用,并且支持多條件的模糊搜索。
4.5 答疑模塊
答疑模塊類似于論壇,一個(gè)提問對應(yīng)多條回答,一個(gè)回答可對應(yīng)多條評論,并且同樣支持富文本。與課程模塊一致,富文本組件同樣使用CKEditor;MongoDB數(shù)據(jù)存儲(chǔ)有著很高的可拓展度,對象、數(shù)組是可以嵌套的,提問與回答與評論的一對多關(guān)系的存儲(chǔ)問題迎刃而解,一個(gè)document對應(yīng)一條提問,多條回答以對象數(shù)組的形式存于document中,一條回答的多條評論以對象數(shù)組的形式存于每個(gè)“回答”對象中,對于前端而言,嵌套的列表渲染即可方便渲染出提問內(nèi)容、回答內(nèi)容、評論內(nèi)容。
4.6 考試模塊、作業(yè)練習(xí)模塊
考試模塊需要實(shí)現(xiàn)選擇題(單選、多選)的自動(dòng)閱卷、評分;而作業(yè)練習(xí)模塊不計(jì)成績,但需在學(xué)生用戶交卷后顯示答案解析。為了能實(shí)現(xiàn)自動(dòng)閱卷、顯示答案解析,我們在交互上的設(shè)計(jì)是引導(dǎo)教師用戶在創(chuàng)建試卷的時(shí)候就需要給每道題設(shè)置正確答案(對于作業(yè)練習(xí)模塊而言還需要答案解析),這些信息連同題干、選項(xiàng)等信息存人數(shù)據(jù)庫中,試卷中每一道題都使用UUID作為唯一標(biāo)識(shí),學(xué)生用戶在進(jìn)入試卷時(shí)后端只返回題干、選項(xiàng)、唯一標(biāo)識(shí)等信息;交卷時(shí)把用戶所選答案、題目唯一標(biāo)識(shí)、試卷唯一標(biāo)識(shí)傳到后端,后端就能把用戶答案與數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行比對,進(jìn)而算出最終成績。而對于考試時(shí)間倒計(jì)時(shí)的計(jì)算,同時(shí)使用前端計(jì)算和后端計(jì)算兩種方式,當(dāng)進(jìn)入考試后前端自動(dòng)設(shè)置定時(shí)器開始倒計(jì)時(shí)并使用WebSocket與服務(wù)器連接,發(fā)送事件,后端接收到事件后開始倒計(jì)時(shí)。后端每隔5分鐘向前端發(fā)送事件使前端的倒計(jì)時(shí)與后端同步,當(dāng)考試倒計(jì)時(shí)變?yōu)?時(shí)后端向前端發(fā)送事件,使其強(qiáng)制交卷以結(jié)束考試。
5 結(jié)束語
本文詳細(xì)分析了一個(gè)基于類MVVM架構(gòu)前端框架Vue JS的在線教學(xué)平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)。該平臺(tái)涉及功能豐富、完整,成功結(jié)合了WebSocket、富文本、Canvas畫圖等技術(shù),體現(xiàn)了Vue JS與其他技術(shù)良好的可結(jié)合性,展示了Vue JS這個(gè)高度遵循MVVM架構(gòu)的前端框架在開發(fā)中的便利,也為相似業(yè)務(wù)需求的平臺(tái)中功能的設(shè)計(jì)實(shí)現(xiàn)提供了一些可行的思路。
參考文獻(xiàn):
[1]易劍波.基于MVVM模式的WEB前端框架的研究[J].信息與電腦:理論版,2016(19):76-77,84.
[2]徐頔,朱廣華,賈瑤,基于Vuejs的WEB前端開發(fā)研究[Jl.科技風(fēng),2017(14):69.
[3]薛玉倩.基于MVVM管理信息系統(tǒng)的研究與應(yīng)用[J].內(nèi)蒙古科技與經(jīng)濟(jì),2019(20):63-64.
[4]朱二華.基于Vue.js的Web前端應(yīng)用研究[J].科技與創(chuàng)新,2017(20):119-121.
[5]馮傳波,彭章友,張鐘浩,基于Vue.js的移動(dòng)應(yīng)用可視化平臺(tái)的研究[J].工業(yè)控制計(jì)算機(jī),2019(5):102-103.
[6]王鵬強(qiáng).基于vue的MVVM框架的研究與分析[J].電腦知識(shí)與技術(shù),2019(11):97-98,100.
[7]何煥春,楊懌,基于MVVM構(gòu)架的Web前端框架研究[J].電腦知識(shí)與技術(shù),2017(24):59-60.
[8]莫文水.Web前端中MVVM框架的應(yīng)用研究[J].網(wǎng)絡(luò)安全技術(shù)與應(yīng)用,2017(4):64.
【通聯(lián)編輯:謝媛媛】