整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          從零開始學(xué)Vue-vue模板和組件

          從零開始學(xué)Vue-vue模板和組件

          我們在前面的章節(jié)中已經(jīng)了解了如何在屏幕上以文本內(nèi)容的形式獲得輸出。在本文中我們將學(xué)習(xí)如何在屏幕上以HTML模板的形式獲得輸出。我們先看一段代碼好來幫助我們理解。

          //index.html
          <!DOCTYPE html>
          <html lang="en">
           <head>
           <meta charset="UTF-8" />
           <meta name="viewport" content="width=device-width, initial-scale=1.0" />
           <meta http-equiv="X-UA-Compatible" content="ie=edge" />
           <title>vue模板和組件</title>
           </head>
           <body>
           <div id="vue_det">
           <h1>姓名 : {{ name }}</h1>
           <div>{{ htmlcontent }}</div>
           </div>
           <script src="https://cdn.jsdelivr.net/npm/vue"></script>
           <script type="text/javascript" src="js/app.js"></script>
           </body>
          </html>
          
          //js/app.js+
          var vm=new Vue({
           el: '#vue_det',
           data: {
           name: "孫悟空",
           htmlcontent: "<div><h1>Vue Js Template</h1></div>"
           }
          })
          

          使用live-server啟動項(xiàng)目得到如下結(jié)果

          因?yàn)槲覀兪褂昧瞬逯担簿褪请p括號,我們在瀏覽器中就真實(shí)的顯示了html內(nèi)容,這顯然和我們想要渲染html是不同的,我們希望它在瀏覽器能顯示html渲染的內(nèi)容。

          v-html

          為了解決上面的問題,我們不得不適用v-html指令,只要我們將v-html屬性分配給html元素,vue就會知道將其作為html內(nèi)容輸出,我們嘗試下:

          <div id="vue_det">
           <h1>姓名 : {{ name }}</h1>
           <div v-html="htmlcontent"></div>
           </div>
          

          得到了如下結(jié)果

          從瀏覽器調(diào)試可以看出

          與app.js中填寫的html字符串表現(xiàn)得相同

          屬性分配

          我們已經(jīng)了解了如何將HTML模板添加到DOM。現(xiàn)在,我們將實(shí)現(xiàn)如何向現(xiàn)有的HTML元素添加屬性。想象一下,我們在HTML文件中有一個圖像標(biāo)記,我們想要分配src屬性,舉例,直接看代碼

           <div id="vue_det">
           <h1>姓名 : {{ name }}</h1>
           <div v-html="htmlcontent"></div>
           <img src="" width="300" height="250" />
           </div>
          

          img標(biāo)簽的src是空的,我們將src放到j(luò)s的數(shù)據(jù)對象中

          var vm=new Vue({
           el: '#vue_det',
           data: {
           name: "孫悟空",
           htmlcontent: "<div><h1>Vue Js Template</h1></div>",
           imgsrc: './img/img.jpg'
           }
          })
          

          然后我們修改index.html

          <img src="{{ imgsrc }}" width="300" height="250" />
          

          結(jié)果如下

          好像哪里不對,其實(shí)不是,在vue中,我們綁定屬性用v-bind指令

           <img v-bind:src="imgsrc" width="300" height="250" />
          

          可以看到我們?yōu)g覽器中渲染的html

          組件

          Vue組件是VueJS的重要功能之一,可以創(chuàng)建自定義元素,可以在HTML中重復(fù)使用。讓我們使用一個示例并創(chuàng)建一個組件。

          //index.html
          <!DOCTYPE html>
          <html lang="en">
           <head>
           <meta charset="UTF-8" />
           <meta name="viewport" content="width=device-width, initial-scale=1.0" />
           <meta http-equiv="X-UA-Compatible" content="ie=edge" />
           <title>vue模板和組件</title>
           </head>
           <body>
           <div id="component_test">
           <testcomponent></testcomponent>
           </div>
           <div id="component_test1">
           <testcomponent></testcomponent>
           </div>
           <script src="https://cdn.jsdelivr.net/npm/vue"></script>
           <script type="text/javascript" src="js/app.js"></script>
           </body>
          </html>
          


          //js/app.js
          Vue.component('testcomponent', {
           template: '<div><h1>This is coming from component</h1></div>'
          });
          var vm=new Vue({
           el: '#component_test'
          });
          var vm1=new Vue({
           el: '#component_test1'
          });
          

          我們創(chuàng)建了兩個div,id分別是component_test和component_test1,在app.js中我們創(chuàng)建了兩個Vue實(shí)例,外加一個Vue組件,要想創(chuàng)建組件,它的語法是

          Vue.component('nameofthecomponent',{ // options});
          

          創(chuàng)建組件后,組件的名稱將成為自定義元素,并且可以在創(chuàng)建的Vue實(shí)例元素中使用相同的名稱,在app.js文件中創(chuàng)建的組件中,我們添加了一個模板,我們已為其分配了HTML代碼。這是一種注冊全局組件的方法,可以將其作為任何vue實(shí)例的一部分,我們發(fā)現(xiàn)這時候?yàn)g覽器變成了

          組件被賦予自定義元素標(biāo)記,即<testcomponent> </ testcomponent>。但是,當(dāng)我們在瀏覽器中檢查相同內(nèi)容時,我們發(fā)現(xiàn)結(jié)果沒有自定義的元素,如以下屏幕截圖所示。

          我們也可以將組件作為vue實(shí)例的一部分

          var vm=new Vue({
           el: '#component_test',
           components:{
           'testcomponent': {
           template : '<div><h1>This is coming from component</h1></div>'
           }
           }
          });
          

          這是本地注冊組件,組件只是vue實(shí)例的一部分。到目前為止我們已經(jīng)基本組件的實(shí)現(xiàn)。現(xiàn)在我們來繼續(xù)擴(kuò)展。

          // js/app.js
          Vue.component('testcomponent', {
           template: '<div v-on:mouseover="changename()" v-on:mouseout="originalname();"><h1>Custom Component created by <span id="name">{{name}}</span></h1></div>',
           data: function () {
           return {
           name: "tom"
           }
           },
           methods: {
           changename: function () {
           this.name="bob";
           },
           originalname: function () {
           this.name="tom";
           }
           }
          });
          var vm=new Vue({
           el: '#component_test'
          });
          var vm1=new Vue({
           el: '#component_test1'
          });
          

          在上面的app.js文件中,我們添加了一個函數(shù),它返回一個對象。該對象具有name屬性,該屬性被賦值為'tom'。盡管這里data是函數(shù),我們也可以像直接在Vue實(shí)例中使用其屬性,此外這里還添加了兩個函數(shù),在changename中,我們更改name屬性,在originalname中我們將其重置為原始名稱,有關(guān)事件我們后面在討論,這段代碼的結(jié)果是:

          因?yàn)榉峙淞薽ouseover和mouseout事件,當(dāng)鼠標(biāo)懸停在tom上時,會將tom改成bob

          動態(tài)組件

          使用關(guān)鍵字<component> </ component>創(chuàng)建動態(tài)組件,并使用屬性綁定,如下

          <component v-bind:is="view"></component>
          
          //index.html
          <!DOCTYPE html>
          <html lang="en">
           <head>
           <meta charset="UTF-8" />
           <meta name="viewport" content="width=device-width, initial-scale=1.0" />
           <meta http-equiv="X-UA-Compatible" content="ie=edge" />
           <title>vue模板和組件</title>
           </head>
           <body>
           <div id="databinding">
           <component v-bind:is="view"></component>
           </div>
           <script src="https://cdn.jsdelivr.net/npm/vue"></script>
           <script type="text/javascript" src="js/app.js"></script>
           </body>
          </html>
          
          //app.js
          var vm=new Vue({
           el: "#databinding",
           data: {
           view: "component1"
           },
           components: {
           component1: {
           template:
           '<div><span style="font-size:25;color:red;">Dynamic Component</span></div>'
           }
           }
          });
          

          瀏覽器已顯示值:

          eb中使用一些圖案做為背景圖案是一種時常可見的,早期一般都是通過圖片來完成。直至CSS一些新特性更趨成熟和穩(wěn)定的時候,會通過CSS的相關(guān)技術(shù),比如CSS的漸變屬性配合background-size之類的來做一些復(fù)雜而又美觀的Web圖案,運(yùn)用于background-image之中。

          而其中最為出名的是@Lea寫的CSS3 Patterns,并且@Lea在其《CSS Secrets》一書中特別介紹了CSS如何實(shí)現(xiàn)復(fù)雜背景圖案。雖然CSS Patterns實(shí)現(xiàn)的圖案是令人感到驚艷與好奇,但其擴(kuò)展性以及適配性還是有一定的限制。因此有同學(xué)將CSS Patterns換成了SVG Patterns(也就是使用SVG相關(guān)的特性實(shí)現(xiàn)了CSS Patterns相同的效果)。當(dāng)然,除此之外,還有很多工具能幫助我們來實(shí)現(xiàn)CSS圖案的效果,其中有的工具可以生成代碼,而有的工具會生成圖片。

          隨著前端技術(shù)不斷的革新,不久前看到一個生成Web圖片的組件:<css-doodle /> —— 使用CSS繪制圖案的Web組件!

          這是一個非常強(qiáng)大的Web組件,初次看到,你會覺得她非常的神奇和強(qiáng)大。至于為什么?你要是花日間閱讀完后面的內(nèi)容,你就知道其中的原委了。為了讓大家對其有初次的感覺,先上一個使用<css-doodle />組件創(chuàng)作的圖案效果,如下:

          是不是有點(diǎn)蠢蠢欲動的感覺。如果是的話,跟著下面的節(jié)奏繼續(xù)往下閱讀。

          什么是<css-doodle />

          <css-doodle />是一個Web組件。其基于Shadow DOM V1Custom Elements V1來構(gòu)建的。該組件可以幫助輕松的使用Custom Elements、Shadow DOM和CSS Grid創(chuàng)建任何你想要的圖案(CSS 圖案)。創(chuàng)建出來的圖案你可以運(yùn)用于Web頁面中。

          當(dāng)你看到Custom Elements、Shadow DOM和CSS Grid的時候,你一定會心卻,這些東西瀏覽器能支持。事實(shí)上你的擔(dān)憂是正常的,因?yàn)樵摻M件到目前為止只在最新的Chrome和Safari瀏覽器上可以正常的運(yùn)行。如果你想運(yùn)用于其他的瀏覽器上,你需要相關(guān)的Polyfilling。

          簡單點(diǎn)說:

          該組件通過其內(nèi)部的規(guī)則(純CSS)會生成一系列的div構(gòu)建的CSS Grid。你可以使用CSS輕松地操作這些div(單元格,每個div就是一個單元格)來生成圖案。生成的圖案既可以是靜態(tài)的,也可以是動態(tài)的。而其限制僅限于CSS本身的限制。

          開始使用<css-doodle />

          使用<css-doodle />組件創(chuàng)建圖案很簡單,當(dāng)然有一個前提是你對其相關(guān)的API和使用方法有所了解。這里先來看怎么在你的項(xiàng)目中使用該組件。

          使用<css-doodle />組件有兩種方法,第一種是比較原始的方法,就是在你的HTML文件中引入該組件所需要的JS和CSS文件。最簡單的方法就是直接引用cdnjs:

          [xml] view plain copy

          <script src="https://cdnjs.cloudflare.com/ajax/libs/css-doodle/0.3.0/css-doodle.min.js"></script>

          這個script你可以在</head>或</body>結(jié)束標(biāo)簽前調(diào)用。然后在任何你想要的地方調(diào)用:

          [xml] view plain copy

          <css-doodle> /* 繪制圖案的代碼放在這里 */

          </css-doodle>

          如果你不想使用cdnjs提供的在線資源,你也可以將css-doodle-0.3.0.min.js文件下載到你本地的項(xiàng)目中,通過相對路徑來引用下載的文件。

          除此之外,也可以通過npm的方式將<css-doodle />安裝到你的項(xiàng)目中,然后通過import的方式將其引入到你的項(xiàng)目中。比如說在Vue項(xiàng)目中,你可以先執(zhí)行:

          npm install css-doodle

          或者使用yarn來安裝:

          yarn add css-doodle

          然后在你想要使用<css-doodle />的地方先import,比如在App.vue文件中:

          [python] view plain copy

          import CSSDoodle from 'css-doodle'

          然后你就可以在<template>中引用,比如:

          這時在你的頁面中看到的效果如下:

          這個時候,你和我可以一樣,對<css-doodle></css-doodle>中代碼一無所知,但正是這里面的一些代碼生成了上圖這樣的效果。這個時候你通過瀏覽器開發(fā)者工具查看代碼的時候,你會看到生成的代碼如下圖所示:

          基本語法

          <css-doodle />的語法是基于CSS的,這一點(diǎn)需要特別記住 —— 一切能用于Web的CSS,都可以用于此處!。除此之外,他還提供了一些額外的實(shí)用函數(shù)和簡寫的屬性。這些函數(shù)和屬性可以在其官網(wǎng)中查閱。

          有關(guān)于<css-doodle />提供的函數(shù)和屬性,在本文章中不做一一介紹,如果你想使用該組件來創(chuàng)作一些有意思的Web圖案,那非常有必要花一定的時間去閱讀官方文檔。并嘗試自己寫寫Demo。你會很快就能掌握這些規(guī)則和使用姿勢!

          先看一個簡單示例

          使用<css-doodle />其后臺運(yùn)行機(jī)制是使用CSS Grid布局創(chuàng)建一個網(wǎng)格系統(tǒng)。其實(shí)創(chuàng)建一個簡單的網(wǎng)格是<css-doodle />最為簡單的一個示例。比如說,我們創(chuàng)建一個5 x 8(五行八列)的網(wǎng)格,并且這個網(wǎng)格的width和其父容器的寬度相同(即100%),高度為瀏覽器屏幕高度的五分之一。那么我們就可以這樣寫代碼:

          你將看到的效果如下:

          特別注意:如果你的瀏覽器看不到任何的效果,請確認(rèn)你使用的是最新版本的Chrome或Safari瀏覽器!后續(xù)的示例不再做相關(guān)的提示!

          為了幫助沒時間閱讀官方文檔的同學(xué)能看懂上面的代碼,這里簡單的做一下說明:

          • :doodle:是一個特殊的選擇器,其指向的是組件元素本身,即<css-doodle />。注意,其樣式會被你的CSS樣式覆蓋
          • @grid:創(chuàng)建一個網(wǎng)格,其后面配置的參數(shù)說明你要創(chuàng)建的網(wǎng)格。比如上面的示例5x8 / 100% 100vh;。其中5 x 8表示的是創(chuàng)建一個五行八列的網(wǎng)格;100%表示網(wǎng)格的寬度(和其容器寬度相同);100vh表示網(wǎng)格的高度(瀏覽器屏幕的高度)
          • :after:每個單元格的偽元素,用于生成內(nèi)容,比如你在效果中看到的數(shù)字
          • @index():是一個函數(shù),返回當(dāng)前單元格的索引號,注意其開始值是從1開始
          • @even:對應(yīng)的偶數(shù)單元格,這里將偶數(shù)單元格的背景顏色設(shè)置為#f36
          • @odd:類似于@even,但對應(yīng)的是奇數(shù)單元格

          再來看一個復(fù)雜的示例

          上面看到的效果是一個簡單的示例效果,使用了一些最基本的樣式規(guī)則寫了一個五行八列的網(wǎng)格。其實(shí)我們還可以利用<css-doodle />提供的一些函數(shù)和一些其他的CSS樣式規(guī)則,制作一些復(fù)雜的效果,而且還可以是帶有動效的。比如下面這個示例:

          對應(yīng)的效果如下:

          效果是不是很炫,很酷!

          • @place-cell:將單元格相對布局
          • @size:設(shè)置單元格的width和height
          • @rand:從數(shù)字的范圍內(nèi)返回一個隨機(jī)值
          • @pick:給定的列表中隨機(jī)選取一個值

          正如你所見,在上面這個示例中,還使用了@keyframe來聲明動畫,并且還使用了CSS自定義屬性。再次驗(yàn)證,只要是瀏覽器支持的CSS屬性都可能用于<css-doodle />。

          帶有交互效果的案例

          上面的示例,使用@keyframes可以做一個帶有動畫的效果。除此之外,還有更神奇的效果,那就是使用<css-doodle />的JavaScript API還可以實(shí)現(xiàn)現(xiàn)有交互效果的圖案。比如下面這個示例:

          當(dāng)我們鼠標(biāo)懸浮在上面的時,圖標(biāo)會旋轉(zhuǎn),這依舊采用的是@keyframes做的一個簡單動畫。除此之外,你點(diǎn)擊屏幕時,整個圖案會更新。

          實(shí)現(xiàn)這樣的效果很簡單,就只是簡單的加了下面這么幾行JavaScript代碼:

          [php] view plain copy

          const myDoodle=document.querySelector('.my-doodle'); myDoodle.addEventListener('click', ()=> { myDoodle.update(); });

          使用了一個.update()函數(shù),當(dāng)你在屏幕單擊時,整個組件會使用給定的樣式重新刷新。

          上面看到的是不同方式實(shí)現(xiàn)的一些圖案效果。除些之外,你可以發(fā)動你的大腦和創(chuàng)意,制作一些其他更有意思的圖案效果。如果你感興趣的話,可以看看@yuanchuan在Codepen整理的有關(guān)于<css-doodle />組件制作的一些圖案效果。

          總結(jié)

          這篇文章主要科普了一下<css-doodle />組件。簡單的回顧一下,該組件是一個Web組件,主要是基于Shadow DOM V1Custom Elements V1 來構(gòu)建的。而其背后運(yùn)行的原理是使用CSS Grid和純CSS規(guī)則制作的一些圖案。除了CSS自帶的規(guī)則之外,該組件還封裝了一些函數(shù)和屬性,能讓你快速制作一些圖案。另外還你還可以使用Unicode字符創(chuàng)建一些字符圖案。

          當(dāng)你閱讀到這里的時候,我想你對<css-doodle />組件有所了解,如果你動手了,或許你創(chuàng)作出一些與眾不同的圖案效果。希望你能在下面的評論中分享您的作品。如果你有其他的想法,也歡迎在下面的評論中分享。最后,該文章要是對您有所幫助的話,歡迎各位爺打個賞,鼓勵我繼續(xù)創(chuàng)作一些優(yōu)質(zhì)的教程。(^_^)

          為開發(fā)人員,我們依賴于靜態(tài)分析工具來檢查、lint(分析)和轉(zhuǎn)換我們的代碼。我們使用這些工具來幫助我們提高生產(chǎn)效率并生成更好的代碼。然而,當(dāng)我們使用markdown編寫內(nèi)容時,可用的工具就很少。

          在本文中,我們將介紹如何開發(fā)一個Markdown擴(kuò)展來解決在使用Markdown管理Django站點(diǎn)中的內(nèi)容時遇到的挑戰(zhàn)。

          你認(rèn)為他們有l(wèi)inter嗎?

          照片來自Pexels,由mali maeder拍攝

          問題

          像每個網(wǎng)站一樣,我們在主頁、FAQ部分和“關(guān)于”頁面等地方都有不同類型的(大部分)靜態(tài)內(nèi)容。很長一段時間以來,我們都是在Django模板中直接管理這些內(nèi)容的。

          當(dāng)我們最終決定是時候?qū)⑦@些內(nèi)容從模板轉(zhuǎn)移到數(shù)據(jù)庫中時,我們認(rèn)為最好使用Markdown。從Markdown生成HTML更安全,它提供了一定程度的控制和一致性,并且對于非技術(shù)用戶來說更容易處理。隨著我們轉(zhuǎn)移過程的進(jìn)展,我們注意到我們遺漏了一些東西:

          內(nèi)部鏈接

          當(dāng)URL更改時,鏈接到內(nèi)部頁面的鏈接可能會中斷。在Django模板和視圖中,我們使用了reverseand {% url %},但是這在普通的Markdown中是不可用的。

          在不同環(huán)境之間進(jìn)行復(fù)制

          絕對內(nèi)部連接不能在不同環(huán)境之間進(jìn)行復(fù)制。這可以使用相對鏈接來解決,不過目前沒有開箱即用的增強(qiáng)這一點(diǎn)的方法。

          無效鏈接

          無效鏈接會損害用戶體驗(yàn),并導(dǎo)致用戶質(zhì)疑整個內(nèi)容的可靠性。這并不是Markdown獨(dú)有的東西,只不過HTML模板是由對URL有一定了解的開發(fā)人員維護(hù)的。另一方面,Markdown文檔是為非技術(shù)寫作人員設(shè)計(jì)的。

          前期工作

          當(dāng)我研究這個問題時,我搜索了Python linters、Markdown預(yù)處理器和擴(kuò)展來幫助生成更好的Markdown。結(jié)果都不是很好。一個引人注目的方法是使用Django模板來生成Markdown文檔。

          使用Django模板預(yù)處理Markdown

          使用Django模板,你可以使用諸如url之類的模板標(biāo)記來反向查詢URL名稱,并配合使用條件、變量、日期格式和所有其他Django模板特性。這種方法本質(zhì)上是使用Django模板作為Markdown文檔的預(yù)處理程序。

          我個人認(rèn)為這可能不是非技術(shù)作家的最佳解決方案。另外,我擔(dān)心提供對Django模板標(biāo)記的訪問可能是危險的。

          使用 Markdown

          對這個問題有了更好的理解之后,我們準(zhǔn)備在Python中更深入地研究Markdown。

          將Markdown轉(zhuǎn)換為HTML

          要在Python中開始使用Markdown,我們先安裝markdown包:

          接著,創(chuàng)建一個Markdown對象并使用其函數(shù)將一些Markdown轉(zhuǎn)換成HTML:

          你現(xiàn)在可以在你的模板中使用這個HTML代碼片段。

          使用Markdown擴(kuò)展

          基本的Markdown處理器提供了生成HTML內(nèi)容的基本要素。對于更“新奇”的選項(xiàng),Python markdown包包含了一些內(nèi)置擴(kuò)展。一個流行的擴(kuò)展是“extra”擴(kuò)展,除了其他東西之外,它增加了對隔離代碼塊的支持:

          為了使用我們獨(dú)特的Django功能擴(kuò)展Markdown,我們將開發(fā)自己的擴(kuò)展。

          創(chuàng)建一個Markdown擴(kuò)展來處理內(nèi)聯(lián)鏈接

          如果你查看源代碼,你將看到要將markdown轉(zhuǎn)換為HTML, Markdown會使用多種不同的處理器。一種類型的處理器是內(nèi)聯(lián)處理器。內(nèi)聯(lián)處理器會匹配特定的內(nèi)聯(lián)模式,如鏈接、反引號、粗體文本和帶下劃線的文本,并將它們轉(zhuǎn)換為HTML。

          我們的Markdown擴(kuò)展的主要目的是驗(yàn)證和轉(zhuǎn)換鏈接。因此,我們最感興趣的內(nèi)聯(lián)處理器是LinkInlineProcessor。這個處理器以[Haki的網(wǎng)站](https://hakibenito.com)的形式獲取markdown ,解析它并返回一個包含鏈接和文本的元組。

          為了擴(kuò)展該功能,我們擴(kuò)展了LinkInlineProcessor并創(chuàng)建了一個Markdown.Extension, 我們用它來處理鏈接:

          我們來將這段代碼分解一下::

          • DjangoUrlExtension擴(kuò)展注冊了一個名為DjangoLinkInlineProcessor的內(nèi)聯(lián)鏈接處理器。這個處理器將取代任何其他現(xiàn)有的鏈接處理器。

          • 內(nèi)聯(lián)處理器DjangoLinkInlineProcessor擴(kuò)展了內(nèi)置的LinkInlineProcessor,并在它處理的每個鏈接上調(diào)用clean_link函數(shù)。

          • clean_link函數(shù)接收一個鏈接和一個域名,并返回一個轉(zhuǎn)換后的鏈接。這就是我們要插入我們的實(shí)現(xiàn)的地方。

          如何獲得網(wǎng)站域名


          要識別到你自己網(wǎng)站的鏈接,你必須知道你的網(wǎng)站的域名。如果你正在使用Django的sites框架,那么你可以使用它來獲取當(dāng)前域名。


          我沒有把它包含在我的實(shí)現(xiàn)中,因?yàn)槲覀儧]有使用sites框架。相反,我們在Django設(shè)置中設(shè)置了一個變量。


          獲取當(dāng)前域名的另一種方法是使用HttpRequest對象。如果內(nèi)容只在你自己的站點(diǎn)中被編輯,你可以嘗試從請求對象中插入站點(diǎn)域名。這可能需要對你的實(shí)現(xiàn)進(jìn)行一些更改。

          要使用該擴(kuò)展,請?jiān)诔跏蓟粋€新的Markdown實(shí)例時添加它:

          太好了,這個擴(kuò)展已經(jīng)被使用了,我們準(zhǔn)備進(jìn)入有趣的部分了!

          驗(yàn)證和轉(zhuǎn)換Django鏈接

          既然我們得到了在所有鏈接上調(diào)用clean_link的擴(kuò)展,那我們可以來實(shí)現(xiàn)我們的驗(yàn)證和轉(zhuǎn)換邏輯。

          驗(yàn)證mailto鏈接

          要開始工作,我們將從一個簡單的驗(yàn)證開始。mailto鏈接對于使用預(yù)定義的收件人地址、主題甚至消息正文打開用戶的電子郵件客戶端非常有用。

          一個常見的mailto鏈接是這樣的:

          這個鏈接將打開你的電子郵件客戶端,并設(shè)置成撰寫一封主題行為“我需要幫助!”的新電子郵件給“support@service.com”。

          mailto鏈接不一定非要包含電子郵件地址。如果你看一看這篇文章底部的“分享”按鈕,你會發(fā)現(xiàn)像這樣的一個mailto鏈接:

          這個mailto鏈接沒有包含收件人,僅包含了主題行和消息正文。

          既然我們已經(jīng)很好地理解了mailto鏈接是什么樣子的,我們就可以向clean_link函數(shù)添加第一個驗(yàn)證:

          為了驗(yàn)證mailto鏈接,我們向clean_link中添加了以下代碼:

          • 檢查鏈接是否以mailto:開頭,以識別相關(guān)鏈接。

          • 使用正則表達(dá)式將鏈接分割到它的組件。

          • 從mailto鏈接中刪除實(shí)際的電子郵件地址,并使用Django的EmailValidator驗(yàn)證它。

          注意,我們還添加了一種名為InvalidMarkdown的新異常類型。我們定義了自己的自定義異常類型,以將它與markdown本身所引發(fā)的其他錯誤區(qū)分開來。

          自定義錯誤類

          我曾經(jīng)寫過關(guān)于自定義錯誤類的文章,為什么它們是有用的,以及你什么時候應(yīng)該使用它們。

          在我們繼續(xù)之前,讓我們添加一些測試,看看它的實(shí)際效果:

          太棒了!按預(yù)期的運(yùn)行了。

          處理內(nèi)部和外部鏈接

          既然我們已經(jīng)了解了mailto鏈接,我們也可以處理其他類型的鏈接:

          外部鏈接

          • 我們的Django應(yīng)用程序外部的鏈接。

          • 必須包含一個頁面跳轉(zhuǎn)協(xié)議(scheme):http或https。

          • 理想情況下,我們還希望確保這些鏈接沒有被破壞,但我們現(xiàn)在不會這樣做。

          內(nèi)部鏈接

          • 到我們的Django應(yīng)用程序中的頁面的鏈接。

          • 鏈接必須是相對的:這將允許我們在不同環(huán)境之間移動內(nèi)容。

          • 使用Django的URL名稱而不是一個URL路徑:這將允許我們安全地來回移動視圖,而不必?fù)?dān)心markdown內(nèi)容中的失效鏈接。

          • 鏈接可能包含查詢參數(shù)(?)和片段(#)。

          SEO

          從SEO的角度來看,公共URL不應(yīng)該改變。當(dāng)他們這樣做的時候,你應(yīng)該使用重定向正確地處理它,否則你可能會受到搜索引擎的懲罰。

          有了這個需求列表,我們就可以開始工作了。

          解析URL名稱

          要鏈接到內(nèi)部頁面,我們希望編寫者提供一個URL名稱,而不是URL路徑。例如,假設(shè)我們有這個視圖:

          這個頁面的URL路徑是https://example.com/, URL名稱是home。我們想要在我們的markdown鏈接中使用這個URL名稱home,就像這樣:

          這將渲染到:

          我們還想支持查詢參數(shù)和散列:

          這將渲染到以下HTML:

          在使用URL名稱時,如果我們更改了URL路徑,內(nèi)容中的鏈接將不會被破壞。要檢查作者提供的href是否是一個有效的url_name,我們可以嘗試reverse它:

          URL名稱“home”指向URL路徑“/”。當(dāng)沒有匹配項(xiàng)時,將會引發(fā)一個異常:

          在我們繼續(xù)之前,當(dāng)URL名稱包含查詢參數(shù)或散列時,會發(fā)生什么:

          這是有意義的,因?yàn)椴樵儏?shù)和散列不是URL名稱的一部分。

          要使用reverse并支持查詢參數(shù)和散列,我們首先需要清除值。然后,檢查它是一個有效的URL名稱,并返回包含查詢參數(shù)和散列的URL路徑,如果提供了的話:

          這個代碼段使用一個正則表達(dá)式來以?或#的出現(xiàn)對href進(jìn)行分割,并返回各部分。

          請確保它可以工作:

          太了不起了!作者們現(xiàn)在可以在Markdown中使用URL名稱了。它們還可以包括要添加到該URL的查詢參數(shù)和片段。

          處理外部鏈接

          要正確處理外部鏈接,我們需要檢查兩件事:

          1.外部鏈接總是提供一個跳轉(zhuǎn)協(xié)議,http:或者h(yuǎn)ttps:。

          2.阻止到我們自己網(wǎng)站的絕對鏈接。內(nèi)部鏈接應(yīng)該使用URL名稱。

          到目前為止,我們已經(jīng)處理了URL名稱和mailto鏈接。如果我們通過了這兩個檢查,這意味著href是一個URL。讓我們從檢查鏈接是否是鏈接到我們自己的網(wǎng)站開始:

          函數(shù)urlparse會返回一個命名元組,該元組包含URL的不同部分。如果netloc屬性等于site_domain,那么該鏈接就確實(shí)是一個內(nèi)部鏈接。

          如果URL實(shí)際上是內(nèi)部的,我們就需要終止。但是,請記住,作者們不一定是技術(shù)人員,因此我們希望幫助他們,并提供一個有用的錯誤消息。我們要求該內(nèi)部鏈接使用URL名稱而不是URL路徑,所以最好讓作者們知道他們提供的路徑的URL名稱。

          要獲得一個URL路徑的URL名稱,Django為我們提供了一個名為resolve的函數(shù):

          當(dāng)找到匹配項(xiàng)時,resolve會返回一個ResolverMatch對象,其中包含URL名稱和其他信息。當(dāng)沒有找到匹配項(xiàng)時,它就會引發(fā)一個錯誤:

          這實(shí)際上就是Django在底層所做的工作,用來確定在一個新請求到來時執(zhí)行哪個視圖函數(shù)。

          為了給作者們提供更好的錯誤信息,我們可以使用來自ResolverMatch對象的URL名稱:

          當(dāng)我們識別出內(nèi)部鏈接時,我們要處理兩種情況:

          • 我們沒有識別出這個URL:這個URL很可能是不正確的。請作者檢查該URL是否有錯誤。

          • 我們識別出了這個URL: 這個URL是正確的,所以就告訴作者應(yīng)該使用什么URL名稱。

          我們來實(shí)際地看一下它:

          漂亮!外部鏈接被接受,內(nèi)部鏈接被拒絕,并帶有一個有用的消息。

          要求跳轉(zhuǎn)協(xié)議

          我們要做的最后一件事是確保外部鏈接包含一個跳轉(zhuǎn)協(xié)議,要么是http:,要么是https:。讓我們將這最后一部分添加到函數(shù)clean_link:

          使用解析后的URL,我們可以很容易地檢查跳轉(zhuǎn)協(xié)議。讓我們確保它正在工作:

          我們向這個函數(shù)提供了一個沒有跳轉(zhuǎn)協(xié)議的鏈接,但是它運(yùn)行失敗了,并顯示了一條有用的消息。太酷了!

          整合代碼

          這是clean_link函數(shù)的全部代碼:

          要了解所有這些特性的一個實(shí)際用例是什么樣子的,請看下面的內(nèi)容:

          這將產(chǎn)生以下HTML:

          不錯!

          結(jié)論

          我們現(xiàn)在有一個很不錯的擴(kuò)展,它可以驗(yàn)證和轉(zhuǎn)換Markdown文檔中的鏈接!現(xiàn)在,在不同環(huán)境之間移動文檔和保持內(nèi)容整潔要容易多了,最重要的是,可以保持正確和最新!

          源碼

          你可以在這個gist中找到全部源代碼。(地址:https://gist.github.com/hakib/73fccc340e855bb65f42197e298c0c7d )

          題外話

          本文中所描述的功能對我們很有用,但是你可能需要根據(jù)自己的需求對它進(jìn)行調(diào)整。

          如果你需要一些想法,那么除了這個擴(kuò)展之外,我們還創(chuàng)建了一個markdown Preprocessor,它允許作者們在markdown中使用常量。例如,我們定義了一個名為SUPPORT_EMAIL的常量,我們像這樣使用它:

          該預(yù)處理程序?qū)⒂梦覀兌x的文本替換字符串$SUPPORT_EMAIL,然后才渲染Markdown。

          英文原文:https://hakibenita.com/django-markdown
          譯者:Nothing

          主站蜘蛛池模板: 亚洲一区二区三区在线观看网站| 在线精品一区二区三区电影| 亚洲乱码一区av春药高潮| 成人精品一区二区三区电影| 国产在线精品一区二区三区直播| 色婷婷av一区二区三区仙踪林| 又硬又粗又大一区二区三区视频 | 日本一道高清一区二区三区| 久久久久国产一区二区三区| 伊人久久精品一区二区三区| 无码精品人妻一区二区三区人妻斩| 人妻无码一区二区三区四区| 在线电影一区二区| 人妻夜夜爽天天爽一区| 精品国产一区二区三区色欲| 午夜福利一区二区三区高清视频 | 国产高清一区二区三区视频| 国产福利微拍精品一区二区| 乱子伦一区二区三区| 久久精品国产一区二区三区肥胖 | 国产一区二区三区播放心情潘金莲 | 日韩人妻无码一区二区三区 | 中文字幕视频一区| 水蜜桃av无码一区二区| 精品人妻码一区二区三区| 日韩精品无码一区二区三区不卡 | 中文字幕亚洲乱码熟女一区二区 | 亚洲国产高清在线精品一区| 国产一区二区高清在线播放| www.亚洲一区| 日韩亚洲一区二区三区| 一区二区三区福利| 极品少妇伦理一区二区| 精品国产一区二区三区| 亚洲乱码av中文一区二区| 国精产品一区一区三区MBA下载| 久久精品日韩一区国产二区 | 国产av天堂一区二区三区| 又硬又粗又大一区二区三区视频| 久久国产免费一区| 无码一区二区波多野结衣播放搜索|