在開始本篇的主題以前,讓咱們把上次遺留下來的問題都清理一下:javascript
axios
請求的地方封裝起來。這裏就不把代碼放在開頭了,相關代碼都放在文末,有興趣瞭解的童鞋能夠先往下翻。html
好了, 咱們如今把上篇剩下的任務給完成了,接下來咱們來正式開始本篇內容吧。vue
字面上意思:去除重複,在項目中,不可避免的會出現重複代碼。可是若是很差好去處理這些重複代碼,那頗有可能就會給你不少「驚喜」。java
如何爲「重複」 下一個定義呢?ios
從最淺顯的層次來看, 相同便是重複。在咱們上面的代碼中,每個組件中都有這麼一行代碼:git
import RequestSender from '@/requestSender';
這就是重複代碼,在每個須要發起請求的組件中你都會須要寫上這麼一行代碼。那麼讓咱們就這個列舉一些可能出現的問題:數據庫
某一天修改了文件名axios
某一天移動了該文件後端
那麼項目中須要修改的地方將會是多少呢?而在修改中會產生手誤的機率又會是多少呢?以上仍是在單人開發的時候,若是團隊協做開發,這些狀況的機率又會是什麼樣的呢。api
固然,對於上面這種引入型的代碼,相似移動文件,修改文件名這種操做。IDE 就能很好的幫你處理,好比 WebStorm
若是你使用重構相關的功能去重命名,那麼它會找出全部 「疑似」引用的代碼片斷,你能夠選擇全部相關的引用同時修改。
這是一種手段,很好的解決了上面這些問題。
那麼讓咱們來看看另外一個重複代碼的問題:
class RequestSender { static GetBlogList() { return axios.get('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/list'); } static Publish(data) { return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/publish', data); } static Login(data) { return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/login', data); } static Signup(data) { return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/signup', data); } }
上面的代碼, 重點不在函數噢。 仔細看看它們有哪些地方重複了。
光從代碼上來看,其實有不少「重複」的地方,好比說 return
、static
、axios.get
、axios.post
。
這些重複有一部分是語法,有一部分是調用。這些都是不可避免的,所以這些重複代碼並不在咱們須要重構的範圍內。那麼,到底是哪段代碼呢?
https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io
準確來講,它並不算是代碼。而是「硬編碼」,從總體代碼上來看,這是目前全部後臺接口的域名
。
在開發過程當中,通常來講至少是會有兩個環境存在:開發環境、線上環境。而它們兩的後臺接口域名通常而言又不會重複,難道每次發佈前都手動改一下域名麼?
咱們先來列舉一下可能會出現的問題:
開發環境、線上環境域名不一致
團隊協做中,開發者之間的開發域名不一致
當線上/開發 環境中的域名須要修改時
能夠看到,當遇到上述問題時,項目中全部硬編碼了域名
的地方都是須要修改的,那麼爲何要修改呢?
除了解決上面列舉的具體問題以外,最根本的目的是:
若是有兩段/多段代碼它們表示的含義徹底一致,而且從目的上來講也是一致的。那麼就應該儘量將其只保留一處定義。
那麼對於這個域名咱們怎麼處理呢?首先將其提煉出來:
static Host = 'https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io';
這樣,引用的地方就能夠這麼寫:
static GetBlogList() { return axios.get(`${Host}/list`); }
這樣,當發現修改的時候,是否是隻須要修改 Host
這麼一個地方就行了呢?、
可是這樣還存在問題,若是要發佈,或者是在 git
、 svn
上協做的時候呢? 每一個人、每一個環境都須要修改這個變量,而且還要在提交代碼時移除掉本身的修改以免衝突。
Host
的例子是很是常見的,當咱們須要發佈、團隊協做的時候,環境不一樣是很是常見的,有可能在本身電腦上 Host
是 localhost:8080
,換在另外一我的電腦上就是 localhost:9099
了。那麼線上環境有可能又是 xxx.xxx.com
、xx.xxx.com/api
諸如此類。
這裏若羽實踐的解決方案是:
將與環境相關的硬編碼提煉成可配置項放入配置文件
配置文件模板化
配置模板文件多樣化
真正的配置文件是不會被提交上去,只有一個模板文件。因爲配置文件並不會被提交,因此開發者之間的環境差別就能夠忽略了,你們根據本身的環境修改配置文件便可。
那麼對於線上環境、測試環境等等,創建對應的配置文件模板便可。當發佈時,使用對應環境的發佈配置文件模板做爲配置文件便可。
那麼咱們來實踐一下:
新建配置模板文件 config.js.template
:
const config = { HOST: '', }; export default config;
接下來複制粘貼模板文件,並重命名爲 config.js
:
const config = { HOST: 'https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io', }; export default config;
接下來修改一下 requestSender.js
:
import axios from 'axios'; import config from '@/config.js'; class RequestSender { static GetBlogList() { return axios.get(`${config.HOST}/list`); } static Publish(data) { return axios.post(`${config.HOST}/publish`, data); } static Login(data) { return axios.post(`${config.HOST}/login`, data); } static Signup(data) { return axios.post(`${config.HOST}/signup`, data); } } export default RequestSender;
好了,如今不論是在任何一個環境下,均可以遊刃有餘的切換域名了。並且這裏面還有一個頗有意思的事情:
簡單來講,咱們在這裏重構了這麼多的代碼,然而咱們並不須要修改任何一個視圖組件中的代碼!!!
表面上仍是原來的樣子,可實際上已經「打掃」過了。這也是重構中須要注意的一點:
上篇中有人問到若羽說封裝請求的意義何在,axios
自己就是帶着 Promise
的支持了。
這裏對這個問題作一個迴應,立場僅表明若羽本人,並不爲任何人「作表明」:
封裝並不是爲了 Promise
,而是爲了將「發送請求」的這個動做封裝起來。由於這屬於數據獲取的行爲,然後面 then
裏的邏輯其實是和業務掛鉤:爲視圖設置數據。這是兩個不一樣的行爲,就像後端同樣:ORM
它僅僅是負責從數據庫中取數據而已,真正對這個數據進行邏輯操做的,並非它。這也是接下來博文的主題:專注,一個函數應當只負責一件事情。
這一篇文章便表示了另外一層意思:去重,在第一層封裝的過程當中咱們發現了域名
的硬編碼問題(不封裝也是同樣),所以在這裏若是不作封裝的話,即便將域名提煉出來,涉及到修改的文件一樣也會較多。不過這種修改是一次性的。
以上即是若羽對上一篇中示例的解釋。
歡迎你們發表評論,共同探討。
edit.vue
:
<script> import RequestSender from '@/requestSender' export default { name: "Edit", data() { return { model: { title: '', content: '', } } }, methods: { submit() { RequestSender.Publish(this.model) .then(res => { if(res.data.Code === 200) { this.$message.success('發佈成功'); } }) } } } </script>
Login.vue
:
<script> import RequestSender from '@/requestSender'; export default { name: "Login", data() { return { model: { username: '', password: '', } } }, methods: { submit() { RequestSender.Login(this.model) .then(res => { if(res.data.Code === 200) { this.$message.success('登陸成功'); } }) } } } </script>
Signup.vue
:
<script> import RequestSender from '@/requestSender'; export default { name: "Signup", data() { return { model: { username: '', password: '', rePassword: '' } }; }, methods: { submit() { if(this.model.password !== this.model.rePassword){ this.$message.error('兩次出入密碼不一致.'); return ; } RequestSender.Signup(this.model) .then(res => { if(res.data.Code === 200){ this.$message.success("註冊成功"); this.$router.push('./login'); } }); } } } </script>
requestSender.js
:
import axios from 'axios'; class RequestSender { static GetBlogList() { return axios.get('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/list'); } static Publish(data) { return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/publish', data); } static Login(data) { return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/login', data); } static Signup(data) { return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/signup', data); } } export default RequestSender;