一、前言 時隔三年,記得第一次寫博客還是2015年了,經過這幾年的洗禮,我也從一個後端的小萌新變成現在略懂一點點知識的文青。如今對於前端的東東也算有一知半解,個人能力總的來說,也能夠獨立開發產品級項目吧。至於為什麼會前端的東西,估計學.NET的人應該大部分都懂些,之前自己搭建過一套框架,但覺得現在的 ...
一、前言
時隔三年,記得第一次寫博客還是2015年了,經過這幾年的洗禮,我也從一個後端的小萌新變成現在略懂一點點知識的文青。如今對於前端的東東也算有一知半解,個人能力總的來說,也能夠獨立開發產品級項目吧。至於為什麼會前端的東西,估計學.NET的人應該大部分都懂些,之前自己搭建過一套框架,但覺得現在的時代趨勢吧,前後端分離是主流,再加上想借這次機會改變部門的開發方式,所以就打算改造一下。
本文僅為個人心得,從實踐項目出發,不講理論,適合萌新學習,如果有說錯了歡迎大家在評論區指出,共同進步,哈哈。
這裡假定大家的前端技術都達到了熟練使用JavaScript、Html和CSS的地步。
二、起步
2.1 Vue入門需要知道的一些基礎知識
- 這是一套用於構建用戶界面的MVVM框架,但有些時候卻又無法實現雙向綁定(需要一些特殊處理,比如子組件更新父組件的屬性)
- 非常容易入門,使用OO思想會讓你更加發現這套框架在應用上的簡單(組件化開發)
- 使用模板語法(Template),在使用的時候就像寫html一樣
- Vue有兩種聲明形式(全局、區域)後面會解釋
- Vue這款框架十分霸道,使用之後會發現以前用的Jquery/Bootstrap會被排斥得很厲害(可是我又很不想放棄這兩者一些生態里的東西,怎麼辦?畢竟Vue現在的生態還不是很好。答案是:不使用vue-cli構建的時候,只能在它的生命周期中創建使用,勉強相容,但是有代碼潔癖的話就會很不舒服。如果使用vue-cli構建之後,通過NPM就可以獲取bootstrap-vue、fontawesome-vue等針對vue開發的新東東)
- 萌新入門,還是按照官方說法,先不要用vue-cli去構建項目(這種感覺對於我這種後端小渣渣是最為清楚,使用之後瞬間感覺前端這幾年變得極度複雜,貌似這樣顯得逼格更高?)
- 下麵就讓我們一步步從簡單的html+js引用的方式使用vue吧,基礎的使用方式在Vue官網里都有,此處就不再對那些內容重寫一遍了。
2.2 Vue頁面級組件的基本結構(每一個頁面對象都大同小異,根據實際需要取捨部分對象屬性即可,記住了就懂了一半)
var Test = new Vue({ el: '#test-vm', // 此處對應html頁面中一個id=test-vm的元素,必須指定 data: { id: 0 // data是組件內部維護的屬性對象 }, computed: { newid: function () { return this.id === 0 // 此處返回一個boolean值,computed是計算屬性的集合體,裡面每一個屬性都是function,因此數據更新時,也會更新對應的視圖數據 } }, methods: { Test: function () { // 方法1內容 }, Test2: function () { // 方法2內容 } }, components: { 'test-input': TestInput // components 是子組件容器,在這裡引入其他要使用的子組件,多個用,分隔。格式為:'組件名':組件對象 (組件名可以自定義,但要和html對應) }, created: function () { // 組件生命周期,此時可以對實例的數據做一些操作,比如用ajax請求數據 }, mounted: function () { // 組件生命周期,執行到這裡說明整個組件已經渲染完成,在這裡你可以執行一些其他操作,比如實例一個bootstrap-datetimepicker組件 }, template: '<div>這是測試內容</div>' // 這是組件的模板,也就是這裡的內容會被載入在上面el指定的#test-vm元素中,這裡要註意的是template必須只有一個root。 // 你不能寫成<div>標題內容</div><div>主體內容</div>,只能加多一層<div><div>標題內容</div><div>主體內容</div></div> });
2.3 Vue組件的基本結構(每一個組件都大同小異,根據實際需要取捨部分對象屬性即可)
// 這是全局聲明組件,這樣每一個引用的組件的components都會預設添加這個組件,就不需要再像上面一樣手動添加 // 局部聲明格式為: var TestInput = { 此處的內容和組件聲明一樣 } // 此處實現了一個文本框(多行/水印/密碼模式/最大值限制/預設值/禁用) Vue.component('test-input', { props: ['type','placeholder','disabled','multiple', 'maxlength', 'val'], data: function () { // 此處的data和頁面級組件的data不同,這裡是一個function,需要把內部維護的屬性通過對象的方式return return { value: '', isError: false, errorMsg: '' } }, computed: { contentLength: function () { return this.value.length; }, typeObject: function () { return this.type ? this.type : 'text'; } }, watch: { // watch是監視器,可以監視組件內部的屬性變化並做出相應處理,屬性命名必須和data或者computed中的屬性一致 contentLength: function (val, oldVal) { if (this.maxlength && val > this.maxlength) { this.value = this.value.substring(0, this.maxlength); } }, val: function (val, oldVal) { if (val) this.value = val; } }, created: function () { if (this.val) this.value = this.val; }, template: '<div class="input-box">' + '<input :disabled="disabled" :type="typeObject" class="form-control" v-if="!multiple" :placeholder="placeholder" v-model="value"/>' + '<textarea :disabled="disabled" class="form-control" v-else :placeholder="placeholder" v-model="value"></textarea>' + '<div v-if="isError">' + '<div>{{errorMsg}}</div>' + '<div class="arrow"></div>' + '</div>' + '<i class="fas fa-exclamation-circle fa-lg" v-if="isError" ></i>' + '<span class="count" v-if="maxlength">{{value.length}}/{{maxlength}}</span>'+ '</div>' });
2.4 子組件更新父組件屬性與父組件控制子組件內容
// 父組件改變子組件的內部屬性 // 父組件內部的屬性通過子組件的props屬性進行傳遞,當父組件屬性值發生改變時,會相應更新子組件視圖,如: // 必須先聲明子組件,才能聲明父組件 var TestInput = { props: ['type'], template:'<input :type="type" ></input>' } var view = new Vue({ el:'#test-vm', data:{ inputType: 'text' }, methods:{ visibleInputText: function () { // 該方法用於轉換子組件文本框的文本類型(密碼/明文) this.inputType === 'text'? this.inputType = 'password' : this.inputType = 'text' } }, components:{ 'test-input':TestInput }, template:'<div>'+ '<button @click="visibleInputText">點擊我修改文本框類型 </button><test-input :type="inputType"></test-input>'+ '</div>' })
// 子組件更新父組件中的屬性 // 子組件通過$emit來將內部的屬性傳遞給父組件中的方法,並通過父組件內部方法來實現更新。簡單點來說就是一個委托方法: // 1.子組件內部聲明委托方法名以及將數據傳遞給$emit(變相地給自己增加了一個隱式方法) // 2.父組件通過綁定子組件聲明的委托方法名把自己的方法傳遞給子組件 var TestInput = { data: function () { return { value: '' } }, methods: { textChange: function () { // $emit 接受[委托方法名,傳遞參數]兩個參數 // 所謂的委托方法名,其實就是父組件中給子組件添加綁定的方法名稱 // 委托方法是一個單參數方法 this.$emit('ontextchange',this.value) } }, template:'<input v-model="value" @onchange="textChange"></input>' } var parent = new Vue({ el: '#text-vm', data: { childContent: '' // 子組件文本框的值 }, methods: { onTextChange: function (value) { // 該方法就是委托的方法,value為子組件傳遞的參數 console.log(value)
this.childContent = value } }, components: { ‘test-input’: TestInput }, template: '<test-input @ontextchange="onTextChange" ></test-input>' // 上面的ontextchange必須和子組件在$emit中聲明的一致 })