Magren

Magren

Idealist & Garbage maker 🛸
twitter
jike

用Vue實現的期末作業

終於度過了緊張刺激的期末以及三個大作業兩個大作業的答辯。
最沒有把握的科目居然是這個學期唯一的開卷考 ——hadoop,考的東西我翻書也翻不到,雖然操作系統也挺難的,但好歹別人是 46 開(平時分占比 6,期末考試占比 4)。
其實主要的還是自己沒怎麼聽,嘿嘿。

#

這個學期我們有一門課是軟體工程,幸運的是這門課沒有期末考,不幸的是這個老師要我們寫 6000 字的論文(6000 字啊!)。
論文是從幾個題目裡面挑一個來寫,基於好寫容易理解同時谷歌 / 百度後有很多樣板以方便我們 copy 的原則,我們小組選了學生學籍管理系統。
老師:“這次作業不查重,你們也不用把這個專案實現,只要模仿我給你們的樣板把他寫出來就好了”
前面 6000 字給我帶來的衝擊小了一半,雖然我文筆挺差,但是我複製粘貼起來真的不含糊。

就這樣我殚精竭虑地想着方法來混過這一次作業。
但是人有時候偷著懶,卻又對別人的努力感到惶恐不安。
快到截止的時間我準備動手的時候,舍友突然在我們的舍友群裡信息轟炸。
“xx 真的把他們選的專案做出來了喂!”
“什麼東西?”
“就是軟體工程那個”
我也可以讚嘆一句,然後就接著躺在床上刷手機,安穩混過這個期末。退一步海闊天空,但是忍一時越想越氣。

Somebody has to win, so why not be me?

我也得動手搞一個,前一陣子看了下 vue,就當作拿來練練手了,這樣就算失敗也是有理由的了吧(自我安慰

一、面向搜索引擎編程#

說實話,因為這是第一次是實際上手,所以我早就想到肯定會踩到很多坑,但是我沒想到一上來就給了我一個下馬威。

頁面最上方存在白條問題#

我開始寫好了一个登錄註冊的頁面,但是無論我怎麼更改 css 屬性,最上方都存在一個白條,特地去谷歌搜索也是搜索出來一堆 css 的屬性設置(雖然的確是樣式的問題)。
最後鑽牛角尖的我不停的翻找答案,最後在一個與這個問題毫不相干的文章上找出了解決的辦法,同時真的給我科普了一波。

首先 index.html 是專案的運行入口,在 body 體中只有一個 div 標籤,其 id 為 app,這個 id 將會連接到 src/main.js 內容,
然後 main.js 中又初始化 vue 的實例,也就是說通過 main.js 我們關聯到 App.vue 組件。
接著在 App.vue 組件中,標籤將會把路由相關內容渲染在這個 div 裡,而路由的內容,則在 index.js 裡。
在 index.js 裡面,將我們寫好的組件發布成路由。

以上就是 vue 專案的運行加載過程,接著在網頁上 F12 查看我的頁面屬性,發現是一個 body 設置了外邊距 8px,但是我寫的登錄頁面(組件)已經設置了背景鋪滿,而我們的組件是渲染到 App.vue 裡的 div,那麼是不是我給 div 添加一個外邊距為 0 的樣式就可以解決?
於是我在 App.vue 裡面的 div 添加樣式,讓它的外邊距為 0,成功顯示了我想要的結果。

<template>
  <div id="app" style="margin: 0px;">
    <router-view/>
  </div>
</template>

因為最終所有的路由都會給加載到 index.html 裡,所以在 html 裡的 body 添加一個外邊距為 0 的樣式也可以解決這個問題。

vuetest_login.png

傳參問題#

首先說說我了解到的頁面之間跳轉傳參的方式,一個是 query,另一個是 params

query 傳參以及接收

傳參

this.$router.push({
       path: '/Home',
       query: {
         id: res.objectId,
       }
     })

接收

this.$route.query.id
params 傳參以及接收

傳參

this.$router.push({
       name: 'Home',
       params: {
         id: res.objectId,
       }
     })

接收

this.$route.params.id

params 傳參的時候,push 裡的路徑只能是填寫 name,params 只能通過 name 來引入路由,如果寫成了 path 則接收參數頁面會顯示 undefind
另外要說的是,query 相當於 get 請求,可以在跳轉後的地址欄上看到參數,而 params 則相當於 post,地址欄看不到傳遞的參數。

好的那麼跳轉頁面傳參的方法我已經知道了,但是當我滿懷期待的傳了個對象的時候,接收到的數據卻是:’[object object]’。
啊???遂檢查了下他的類型,就是一個 String……
我對象呢?我對象呢!

也是通過谷歌後解決,在傳遞之前先把對象轉換成 json 字符串:

JSON.stringify(res); 

然後再接收的頁面將 json 字符串轉換回對象

JSON.parse(this.$route.query.res)

關於 v-bind 和 v-model#

這兩個東西在我趕這個專案的時候經常出現,也讓我經常把這兩個搞混,畢竟都是綁定數據。

v-bind

v-bind 只能實現一個單向的綁定,即從 model 到 view,無法實現雙向綁定。
可用來綁定文本:

<p>{{message}}</p>
<p v-bind="message"></p>

也可用來綁定屬性:

<img v-bind:src="res">
v-model

v-model 可以實現雙向的綁定,但是他有個限制就是只能用於表單當中。
綁定 text:

<input type="text" v-model="val" />

綁定 radio:

<input type="radio" value="one" v-model="radioResult" />
<input type="radio" value="two" v-model="radioResult" />

在這裡 radioResult 的值,隨著單選框的點擊,會成 one 或 two

點擊圖片更換圖片#

這個功能有點取巧,一開始我還傻傻的轉不過腦子來,後面看了別人實現才覺得妙啊……
首先我們寫一個圖片的標籤,以及一個文件選擇的標籤,同時給圖片添加一個點擊監聽事件:

<img  v-bind:src="icon" @click="selectIcon" class="icon">

接著我們要隱藏我們的文件選擇的標籤,即設置 display 樣式,同時用 ref 屬性註冊一個引用信息,方便在方法中調用,還有設置 change 事件。如果需要多選的話可以設置 multiple 屬性:

<input type="file" ref="btn_file" @change="getFile" style="display:none">

這個時候是只能看見我們的圖片但是看不到我們的文件選擇按鈕的,在圖片點擊後觸發的方法中,我們通過 $refs 引用我們的文件選擇按鈕,同時觸發它:

selectIcon: function(){
          let selectFile = this.$refs.btn_file;
          selectFile.click();
      }

這個時候我們的文件選擇就會觸發,選擇我們的圖片後會觸發其 change 事件:

getFile: function(){
           this.file = event.target.files[0];
           //判斷選中文件的格式
           if(this.file.type!="image/png"&&this.file.type!="image/bmp"&&this.file.type!="image/jpeg"&&this.file.type!="image/jpg"){
               window.alert("僅支持png、bmp、jpeg、jpg文件");
               return;
           }
           //該方法返回一個DOMString包含了一個對象URL,該URL指定文件的內容。
           this.icon = window.URL.createObjectURL(this.file);
       }

限制文件上傳的類型其實也可以在標籤中添加 accept 屬性,即:accept=“image/gif, image/jpeg”
假如不限制圖像格式的話也可以寫成: accept="image/*"
但是 accept 這個屬性並不建議使用,因為一方面在部分瀏覽器上會響應很慢或者不支持,並且有時候還是可以選擇到指定格式之外的文件。
應通過 js 驗證或者後台伺服器判斷。

組件中引用別的組件同時傳遞數據#

在做專案的首頁的時候我需要通過點擊旁邊的菜單欄不同的欄目,在右邊的界面中呈現不同的界面,於是我就想到了通過點擊然後切換右邊不同的子組件。
寫好一個組件後,我首先得把它引用到當前的組件中:
import selectClass from '…/components/selectClass’
接著在 components 聲明:

components: {
  selectClass
},

在 data 中聲明:

data(){
  return{
    ···
    selectClass:'selectClass',
    ···
  }
}

在需要的地方中用 is 引入就好了:

<div :is="contentView" ></div>

接下來就是要從父組件中傳參到子組件,有幾種傳遞方式,我這裡選用的是 props
通過 v-bind 將動態 props 綁定到父組件的數據,父組件的數據發生改變,子組件也會隨之改變:

<div :is="contentView"   v-bind:objectId="objectId"></div>

接著在子組件中,用 props 獲取:

<script>
  export default{
    props:['objectId']
    data(){
      return{

      }
    }
  },
  ······
</srcipt>

接著我們就可以在子組件中通過 this.objectId 來調用父組件中傳來的參數了。

二、最後#

因為這是三天趕出來的東西(要交上去了),所以我對自己第一次用 vue 寫的這個專案還是比較滿意的(嘿嘿),但是就目前來看的話應該還有很多可以優化的東西,仔細想想應該趁熱打鐵,深一點了解後再去學別的東西吧,還有自己在 css 樣式上不是非常熟練,果然看看是不行的,親自寫一遍總是可以踩到非常多的坑,不能自滿。

這次的期末作業事件應該可以說是一個混子被迫運營吧。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。