單詞翻譯常見於APP中,那麼在網頁中對於一段中英混雜的內容怎麼準確的作到單詞的翻譯呢?html
我要渲染的內容是一段段的html,用react渲染一段html內容是沒有什麼難度,使用dangerouslySetInnerHTML 便可。可是能夠作到將內容中的英文單詞翻譯出來,是怎麼實現的呢?一塊兒來看一下吧。前端
我前端是作內容展現,後臺將Html格式的內容傳遞到前端,前端原生元素的dangerouslySetInnerHTML 屬性去解析html內容,就可使用react框架渲染html了node
仔細看,這個屬性用的是{{ }}2個括號而不是1個括號。緣由是:第一{}表明jsx語法開始,第二個是表明dangerouslySetInnerHTML接收的是一個對象鍵值對。它接收的內容是html的,很容易收到XSS攻擊,因此這個屬性有了dangerous這個單詞...react
既然要提取出來作單詞翻譯,就得有能力去獲取每個單詞,因此個人打算是,把內容提取出來,是一個英文單詞就放進一個span標籤中。可是這一步在哪裏處理比較好呢,我想了想,在頁面渲染以前處理吧, 這樣頁面渲染的壓力要減少,提升渲染速度。因此我在前端接收到後端發送的數據以後,在存入store以前就先處理好。web
case "OBT_BOOK_CONTENT_SUCCESS":
var newContents = action.meta.bookcontent.map((item, index) => {
item.paragraphContent = item.paragraphContent.replace(/src="/g, `src="${url}`);
//處理caseContent中的單詞
var div = document.createElement('div');
div.innerHTML = item.paragraphContent;
var caseContent = div.querySelector('.caseContent');
if (caseContent) {
var arr = caseContent.innerText.split(" ");
for (var i = 0; i < arr.length; i++) {
arr[i] = "<span>" + arr[i] + "</span>"
}
caseContent.innerHTML = arr.join("");
item.paragraphContent = div.innerHTML;
}
return item;
})
return Object.assign({}, state, {
bookcontent: newContents
})
複製代碼
因爲傳給個人是一大段內容,裏面的元素的類型不僅一種、類名也不止一種,有div .caseTitle .caseContent strong等等,可是我只處理面積最大的一塊英文,也就是隻處理caseContent中的英文單詞這就好辦了。我沒有用string的方法,去查找這個串在什麼位置,怎麼截取怎麼拼接。沒有。我利用了DOM的原理,藉助DOM原生的api幫助我獲得我要的英文單詞。我建立了一個div(沒有DOM我就本身建立DOM咯),而後DOM查找.caseContent,用空格把其中的全部單詞提取出來,再給每個單詞用span包起來,而後把.caseContent中的內容替換掉,同時div的innerHTML也就變了,最後改變paragraphContent。就這樣把後端傳過來的東西作了修改,再使用。後端
if(e.target.nodeName === 'SPAN'){
var s = "";
if(e.target.innerText) {
var len = e.target.innerText.length;
if( !/^[\u4e00-\u9fa5]{0,}$/.test(e.target.innerText) ){
if(e.target.innerText[len -1 ] === ',' || e.target.innerText[len -1 ] === '.' ){
s = e.target.innerText.substring(0, len -1 )
}else {
s = e.target.innerText;
}
var chooseSpan = e.target;
this.props.checkWords(s, chooseSpan);
}
}
console.log( s);
}
複製代碼
利用正則!/^[\u4e00-\u9fa5]{0,}$/
提取出來英文單詞,可是有些單詞末尾會帶着英文狀態下的逗號,句號.,因此還須要用substring
剪切一下單詞,再調用方法。api
這裏,提取頁面中點擊的內容,須要CSS的配合。bash
user-select: text;
複製代碼
user-selct: text;可讓頁面中的內容被選中。而 user-select: none是讓頁面中的內容不被選中。app
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
複製代碼
獲取了單詞s以後,還須要作一點交互,就是被選中的單詞高亮起來,全部,span元素也須要被處理,爲了嚴謹,因此須要再判斷是否是單詞,是的話,再對span 作處理。框架
checkWords(txt, selectedSpan) {
// 查單詞
this.selectedSpan = selectedSpan;
if (txt.toString().length > 1) {
if (/^\w+$/.test(txt)) {
this.props.getWord(txt);
this.setState({
showWord: true
})
selectedSpan.style.color="#fff";
selectedSpan.style.backgroundColor="rgb(0,153,223)";
}
}
}
複製代碼
var appSecret = 'GOPjZoiSnH592P31Qn6xoallHn3zUnSh';
var appKey = '06fc15a9c06cb290';
var salt = '' + (new Date).getTime();
// 多個query能夠用\n鏈接 如 query='apple\norange\nbanana\npear'
var from = 'en';
var to = 'zh-CHS';
var str1 = appKey + q + salt + appSecret;
var data = null;
var sign = md5(str1);
var sendRes = res;
sign = sign.toUpperCase();
q = encodeURI(q);
var url = `http://openapi.youdao.com/api?q=${q}&from=${from}&to=${to}&appKey=${appKey}&salt=${salt}&sign=${sign}`
複製代碼
有了這個url以後,就能夠請求了。返回的東西是:
播放單詞的地方就是用 H5的audio 元素,src是 http://dict.youdao.com/dictvoice?audio=${this.props.word.query}
<audio id="audio" >
<source src={voiceUrl} type="audio/mp3"></source>
</audio>
複製代碼
後來發現扇貝的單詞api作的也不錯,沒有有道用的這麼麻煩,有道還須要簽名,用戶量大的時候也會有限制,準備之後換扇貝的。
至此,使用react框架完成移動頁面的定向單詞翻譯已完成。其中配合了CSS,DOM,正則,使用別家api等知識,算是一次小小的綜合考覈吧,不知道有沒有其餘同窗也作過這樣的事情,若是有的話,能夠交流一下啊。