// 全局定義
Vue.component('my-lists', {
// options
})
複製代碼
定義後,能夠在template
模版中使用<my-list></mylist>
,此時會將組件中定義的內容顯示出來。html
<template>
<div>
<my-list></mylist>
</div>
</template>
複製代碼
經過例子來看一下vue
<body>
<div id='app'>
<my-list></my-list>
</div>
</body>
<script>
Vue.component('my-list', {
template: `
<ul>
<li>上海</li>
<li>北京</li>
<li>南京</li>
</ul>
`
})
new Vue({
el: '#app'
})
</script>
複製代碼
頁面會顯示出咱們定義的my-list
的組件內容,``
這個符號是ES6中的模版字符串,想詳細瞭解的話,能夠看MDN上關於模版字符串的說明。vuex
若是不須要全局定義的話,那能夠在Vue實例中局部定義vue-cli
var myList = {
template: `
<ul>
<li>上海</li>
<li>北京</li>
<li>南京</li>
</ul>
`
}
new Vue({
el: '#app', // 掛載
components: {
'my-list': myList
}
})
複製代碼
data
上面是簡單的組件,若是咱們想本身經過變量,來控制列表的展現,這個時候,咱們組件內部定義data
。咱們來從新寫my-list
組件:npm
var citys = ['上海', '北京', '廣州']
Vue.component('my-list', {
template: `
<ul>
<li v-for='(item, index) in citys' :key='index'>{{item}}</li>
</ul>
`,
data () {
return {
citys: citys
}
}
})
new Vue({
el: '#app'
})
複製代碼
有一點要注意,data
必須是一個函數,將值經過函數返回。若是是一個變量:數組
var citys = ['上海', '北京', '廣州']
Vue.component('my-list', {
template: `
<ul>
<li v-for='(item, index) in citys' :key='index'>{{item}}</li>
</ul>
`,
data: {
citys: citys
}
})
複製代碼
會致使一個問題,多個相同組件同時使用時,它們的data
是共享的,會出現相互影響的狀況。相似於淺拷貝的這種狀況bash
var a = {name: 'a'}
var b = a
var c = a
console.log(b.name, c.name) // a a
console.log(b.name, c.name) // a a
b.name = 'b'
console.log(b.name) // b
console.log(c.name) // b
// b是copy a的引用,因此b改變了的同時會影響a
// 組件內的data同理,因此將data的值以函數返回,以建立不一樣的對象,而不是共享一個
var a = function () {
return {
name: 'a'
}
}
var b = a() // b是新對象
var c = a() // c也是新對象
b.name = 1
console.log(c.name) // a
複製代碼
Props
給子組件emit
觸發事件,告訴父組件發生了什麼v-on
/@
監聽這個事件以上述的my-list
爲例子,實現當點擊城市名稱時,會在下方顯示點擊的城市:app
<body>
<div id='app'>
<my-list
:citys='citys'
@select='getCity'></my-list>
<p>{{selCity}}</p>
</div>
</body>
<script>
Vue.component('my-list', {
template: `
<ul>
<li
v-for='(item, index) in citys'
:key='index'
@click='select(item)'>{{item}}</li>
</ul>
`,
props: ['citys'],
methods: {
select (city) {
this.$emit('select', city)
}
}
})
new Vue({
el: '#app',
data () {
return {
citys: ['上海', '北京', '廣州'],
selCity: ''
}
},
methods: {
getCity (city) {
this.selCity = city
}
}
})
</script>
複製代碼
:citys
動態綁定props
的用戶,:
是v-bind的縮寫
;若是傳遞的是一個靜態的值,則能夠直接寫成citys="['上海','北京']"
@select
父組件監聽子組件觸發的事件this.$emit('select', city)
; @
是v-on
的縮寫;若是子組件觸發了select
,會響應父組件的'getCity'函數咱們須要注意的是,父子組件通訊是單向的,即父組件傳遞給子組件的props
發生變化時,子組件也會接收到這種變化,可是若是子組件改變props
的值時,不會反饋給父組件,防止修改了父組件的狀態,致使整個的數據流難以理解,若是修改了,Vue也會發出警告。 props
對於子組件來講應該是隻讀的。有兩種狀況下,咱們會想改變props
:異步
computed
來計算處理後的變量computed: {
newCitys () {
this.citys.filter((ele) => {
return ele !== '上海'
})
}
}
複製代碼
props
賦值給自身的屬性data () {
return {
initCitys: this.citys
}
}
複製代碼
若是咱們想修改props
的值,並將變化反饋給父組件,除了$emit
觸發事件 + 父組件監聽事件這種方式外,還有一種較爲簡單的方式,經過sync
操做符編輯器
// 父組件
<child-component :name.sync='name'></child>
// 子組件想要可以修改name,能夠這麼作
this.$emit('update:name', 'newVal')
複製代碼
上述咱們是直接傳遞props
,咱們能夠在子組件中經過定義props
的格式來對props
進行簡單的驗證,如下一段驗證代碼來自官網,容許偷個懶= _=||
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
}
}
}
})
複製代碼
在複雜項目中,可能會出現多個同級的組件須要通訊,而僅僅是簡單的父子組件通訊,這個時候怎麼去作呢?
var emitEvent = new Vue()
// 在不一樣的組件中,經過觸發事件,監聽事件來實現通訊
emitEvent.$emit('event-name', val)
emitEvent.$on('event-name', funciton (val) {
})
複製代碼
Vuex
Vuex
是一個專門爲Vue.js
開發狀態管理軟件。 Vuex中有幾個核心的概念
State 存儲狀態,相似於data屬性
Getter 從state
中派生出一些屬性,相似於computed
Mutation 更改state
的屬性,state
屬性是沒法直接經過賦值進行更改的,須要經過Mutation
定義的函數來進行賦值,提交的是state
Actions Mutation
必須是同步的函數,因此在Actions中處理異步的操做,而且提交的是Mutation
Module 當項目很大的時候,須要根據不一樣的功能分割成不一樣的模塊,每次須要的時候,只須要引用須要的模塊便可
好比一個項目中使用Vuex,首先安裝Vuex npm install vuex --save
,經過腳手架vue-cli
,通常默認自帶Vuex
Vuex.store的目錄結構能夠是這樣的
store
- index.js // 統一模塊的index
- modules
- a.js // 模塊 a
- b.js // 模塊 b
複製代碼
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import a from './modules/a'
import b from './modules/b'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
a,
b
}
})
複製代碼
store/modules/a.js
export default {
namespaced: true, // 必要的
state: {
data: null
},
mutations: {
setData(state, data) {
state.data = data
}
},
actions: {
getData (context, cb) {
// 假設執行的從服務端獲取的數據
http.post(url, {name: 'b'}, function (res) {
// 提交mutation操做
context.commit('setData', res)
// 若是有回調函數的話
typeof cb === 'funciton' && cb(res)
})
}
}
}
複製代碼
store/modules.b.js 相似於a,在此就不舉例子了。
在組件中如何是使用呢?
首先導入Vuex提供的方法
// components/a.vue
// 首先,肯定須要哪些功能
// 若是隻須要state中的數據
import { mapState } from 'vuex'
// 若是隻須要state中的數據 和 mutations操做
import { mapState, mapMutations } from 'vuex'
// 若是還對Actions有需求
import { mapState, mapMutations, mapActions } from 'vuex'
// 須要什麼導入什麼便可
// 小tips: 能夠先寫 from 'vuex',再寫{}中的,編輯器會自動不全
複製代碼
而後導入咱們在Store中定義的屬性和方法
# 使用 a 模塊,而且把a模塊中的data賦值給aData
computed: {
...mapState('a', {
aData: state => state.data
})
...mapGetters('a', {
xxx: state => state.xxx
})
}
# 導入方法
methods: {
...mapMutations('a', [
'setData'
])
...mapActions('a', [
'getData'
])
}
複製代碼
使用屬性和方法
// 屬性和方法經過this調用
this.aData
// 從新賦值
this.setData('aaa')
// 傳入回調函數
this.getData(function (res) {
console.log(res)
})
複製代碼
上面的代碼中咱們使用...
Javascript的擴展操做符和 aData: state => state.data
的箭頭函數,若是對這兩項有不瞭解的,能夠查閱連接
感謝,若是有什麼寫的很差的地方,請聯繫做者,比心~