注冊組件就是利用Vue.component()方法,先傳入一個自定義組件的名字,然后傳入這個組件的配置。
在陽谷等地區,都構建了全面的區域性戰略布局,加強發展的系統性、市場前瞻性、產品創新能力,以專注、極致的服務理念,為客戶提供網站設計、成都網站設計 網站設計制作按需設計,公司網站建設,企業網站建設,品牌網站建設,營銷型網站,成都外貿網站建設公司,陽谷網站建設費用合理。
Vue.component('mycomponent',{ template: `這是一個自定義組件`, data () { return { message: 'hello world' } } })
如上方式,就已經創建了一個自定義組件,然后就可以在Vue實例掛在的DOM元素中使用它。
直接使用Vue.component()創建的組件,所有的Vue實例都可以使用。還可以在某個Vue實例中注冊只有自己能使用的組件。
var app = new Vue({ el: '#app', data: { }, components: { 'my-component': { template: `這是一個局部的自定義組件,只能在當前Vue實例中使用`, } } })
注意:組件的模板只能有一個根元素。下面的情況是不允許的。
template: `這是一個局部的自定義組件,只能在當前Vue實例中使用 hello`,
可以看出,注冊組件時傳入的配置和創建Vue實例差不多,但也有不同,其中一個就是data屬性必須是一個函數。這是因為如果像Vue實例那樣,傳入一個對象,由于JS中對象類型的變量實際上保存的是對象的引用,所以當存在多個這樣的組件時,會共享數據,導致一個組件中數據的改變會引起其他組件數據的改變。
而使用一個返回對象的函數,每次使用組件都會創建一個新的對象,這樣就不會出現共享數據的問題來了。
當使用 DOM 作為模版時 (例如,將 el 選項掛載到一個已存在的元素上), 你會受到 HTML 的一些限制,因為 Vue 只有在瀏覽器解析和標準化 HTML 后才能獲取模板內容。尤其像這些元素
在自定義組件中使用這些受限制的元素時會導致一些問題,例如:
自定義組件 被認為是無效的內容,因此在渲染的時候會導致錯誤。這時應使用特殊的 is 屬性:
也就是說,標準HTML中,一些元素中只能放置特定的子元素,另一些元素只能存在于特定的父元素中。比如table中不能放置div,tr的父元素不能div等。所以,當使用自定義標簽時,標簽名還是那些標簽的名字,但是可以在標簽的is屬性中填寫自定義組件的名字。
應當注意,如果您使用來自以下來源之一的字符串模板,這些限制將不適用:
當父組件傳遞值為基本類型時,在子組件中更改這個屬性會報錯。正確的做法是,在父組件中綁定屬性值時,加上.sync修飾符。
然后在子組件中改變相應的屬性
methods: { changeArray () { this.counter++ this.$emit('update:childArray', this.counter) } }
一般來說,是不建議在子組件中對父組件中傳遞來的屬性進行操作的。如果真的有這種需求,可以這樣:
父組件傳遞了一個基本類型值,那么可以在子組件中創建一個新的屬性,并以傳遞進來的值進行初始化,之后就可以操作這個新的屬性了
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
父組件傳遞了一個引用類型值,為了避免更改父組件中相應的數據,最好是對引用類型進行復制。復雜的情況,肯定應該是深復制。
同樣是上面的原因,靜態的給子組件的特性傳遞值,它都會把他當做一個字符串。
子組件中,特性的值是字符串 "1" 而不是 number 1。如果想傳遞正確的數值,應該使用v-bind傳遞,這樣就能把傳遞的值當做一個表達式來處理,而不是字符串。
我們可以給組件的props屬性添加驗證,當傳入的數據不符合要求時,Vue會發出警告。
Vue.component('example', { props: { // 基礎類型檢測 (`null` 意思是任何類型都可以) propA: Number, // 多種類型 propB: [String, Number], // 必傳且是字符串 propC: { type: String, required: true }, // 數字,有默認值 propD: { type: Number, default: 100 }, // 數組/對象的默認值應當由一個工廠函數返回 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 自定義驗證函數 propF: { validator: function (value) { return value > 10 } } } })
type 可以是下面原生構造器:
StringNumberBooleanFunctionObjectArraySymboltype 也可以是一個自定義構造器函數,使用 instanceof 檢測。
// 自定義Person構造器 function Person(name, age) { this.name = name this.age = age } Vue.component('my-component', { template: `名字: {{ person-prop.name }}, 年齡: {{ person-prop.age }} `, props: { person-prop: { type: Person // 指定類型 } } }) new Vue({ el: '#app2', data: { person: 2 // 傳入Number類型會報錯 } })
也可以像在html標簽中添加data-開頭的自定義屬性一樣,給自定義組件添加任意的屬性。而不僅限于data-*形式,這樣做的話,Vue會把這個屬性放在自定義組件的根元素上。一個自定義組件的模板只能有一個根元素。
如果父組件向子組件的非prop屬性傳遞了值,那么這個值會覆蓋子組件模板中的特性。
上面渲染的結果是,div的att屬性是helloParent。注意:前面已經提到過,覆蓋原則對于class和style不適用,而是采用了合并(merge)的原則。
上面的渲染結果是,div的類名是class1 class2,行內樣式是color:red; background:yellow;。
通過prop屬性,父組件可以向子組件傳遞數據,而子組件的自定義事件就是用來將內部的數據報告給父組件的。
如上所示,共分為以下步驟:
子組件在自己的方法中將自定義事件以及需要發出的數據通過以下代碼發送出去
this.$emit('myclick', '這是我暴露出去的數據', '這是我暴露出去的數據2')
第一個參數是自定義事件的名字后面的參數是依次想要發送出去的數據父組件利用v-on為事件綁定處理器
這樣,在Vue實例的methods方法中就可以調用傳進來的參數了
注意: 在使用v-on綁定事件處理方法時,不應該傳進任何參數,而是直接寫v-on:myclick="onClick",不然,子組件暴露出來的數據就無法獲取到了
如果想在某個組件的根元素上監聽一個原生事件。可以使用 .native 修飾 v-on
v-model可以對表單控件實現數據的雙向綁定,它的原理就是利用了綁定屬性和事件來實現的。比如input控件。不使用v-model,可以這樣實現數據的雙向綁定:
{{text}}
上面的代碼同樣實現了數據的雙向綁定。其本質就是:
把input的value特性綁定到Vue實例的屬性text上,text改變,input中的內容也會改變然后把表單的input事件處理函數設置為Vue實例的一個方法,這個方法會根據輸入參數改變Vue中text`的值相應的,在input中輸入內容時,觸發了input事件,把event.target.value傳給這個方法,最后就實現了改變綁定的數據的效果。而v-model就是上面這種方式的語法糖,也就是把上面的寫法封裝了一下,方便我們使用。
理解了v-model的內幕,也就可以把這個效果用在自定義表單組件上了。來實現一個簡單的只能輸入hello的表單輸入組件。
{{hello}}
默認情況下,一個組件的 v-model 會使用 value 屬性和 input 事件,但是諸如單選框、復選框之類的輸入類型可能把 value 屬性用作了別的目的。model 選項可以回避這樣的沖突:
Vue.component('my-checkbox', { model: { prop: 'checked', // 將輸入的特性改為checked event: 'change' // 觸發的自定義事件類型為change }, props: { checked: Boolean, // this allows using the `value` prop for a different purpose value: String } })
這樣設置的話,
上面的代碼就等同于
{ foo = val }" value="some value">
實際使用時,與之前不同的地方是:
把子組件中接收外部數據的prop屬性改為checked向父組件發出事件時,事件類型應改為change
Vue.component('my-component3', { template: ``, props: ['checked'], // 屬性名改變 model: { prop: 'checked', event: 'change' }, methods: { checkInput (value) { var hello = 'hello' if (!hello.includes(value)) { this.$emit('change', hello) // 事件類型改變 this.$refs.input.value = hello } else { this.$emit('change', value) // 事件類型改變 } } } })
通過使用保留的 元素,動態地綁定到它的 is 特性,可以讓多個組件使用同一個掛載點,并動態切換:
home post about
也可以直接綁定到組件對象上:
var Home = { template: `這是home組件` } new Vue({ el: '#app6', data: { currentComponent: Home } })
如果把切換出去的組件保留在內存中,可以保留它的狀態或避免重新渲染。為此可以添加一個 keep-alive 指令參數:
終于到了基本知識的最后一個了。官網寫的很詳細。
上面用到的很多組件的使用方式是這樣的:
也就是說組件中是空的,沒有放置任何文本或元素。但是原生的html元素都是可以進行嵌套的,div里面放table什么的。自定義組件開閉標簽之間也可以放置內容,不過需要在定義組件時使用slot。
slot相當于子組件設置了一個地方,如果在調用它的時候,往它的開閉標簽之間放了東西,那么它就把這些東西放到slot中。
當子組件中沒有slot時,父組件放在子組件標簽內的東西將被丟棄;子組件的slot標簽內可以放置內容,當父組件沒有放置內容在子組件標簽內時,slot中的內容會渲染出來;當父組件在子組件標簽內放置了內容時,slot中的內容被丟棄子組件的模板:
我是子組件的標題 只有在沒有要分發的內容時才會顯示。
父組件模板:
我是父組件的標題 這是一些初始內容
這是一些初始內容
渲染結果:
我是父組件的標題 我是子組件的標題 這是一些初始內容
slot可以有很多個。那么子組件對于父組件放置的多余的內容如何放到各個slot中呢?方法就是子組件給每個slot起一個名字name,父組件放置多余的元素時,給每個元素的slot屬性分配一個代表slot的名字。到時候,多余的內容就會根據自己的slot屬性去找具有對應名字的slot元素。
注意:
子組件可以有一個匿名的slot,當分發的多余內容找不到對應的slot時,就會進入這里面如果子組件沒有匿名的slot,當分發的多余內容找不到對應的slot時,就會被丟棄例如,假定我們有一個 app-layout 組件,它的模板為:
父組件模版:
這里可能是一個頁面標題 主要內容的一個段落。 另一個主要段落。 這里有一些聯系信息
主要內容的一個段落。
另一個主要段落。
這里有一些聯系信息
渲染結果為:
這里可能是一個頁面標題 主要內容的一個段落。 另一個主要段落。
作用域插槽也是一個插槽slot,但是他可以把數據傳遞給到父組件的特定元素內,然后有父組件決定如何渲染這些數據。
首先,子組件的slot需要有一些特性(prop)
Vue.component('my-component4', { template: ` `, data () { return { hello: [1,'2'] } } })
父組件在調用子組件時,需要在里面添加一個template元素,并且這個template元素具有scope特性
scope特性的值,就代表了所有子組件傳過來的數據組成的對象。相當于
props = { text: '', message: '' }
最后,父組件就可以在template中渲染子組件傳過來的數據了
{{props.text}} {{props.message}}
最新的Vue支持將作用域插槽的屬性解構。所以上述代碼可以簡寫為:
{{text}} {{message}}
作用域插槽也是插槽,只不過是多加了些特性,然后父組件多進行了些處理。
以上即是個人對Vue中的組件的理解,希望對大家有所幫助