java開發兩年,連Spring的依賴注入的方式都搞不清楚,你工作可能有點懸!
元件化開發
基本概念
vue.js 有兩大法寶,一個是資料驅動,另一個就是元件化
什麼叫元件化
所謂元件化,就是把頁面拆分成多個元件,每個元件依賴的 CSS、JS、模板、圖片等資源放在一起開發和維護。
因為元件是資源獨立的,所以元件在系統內部可複用,元件和元件之間可以巢狀,如果專案比較複雜,可以極大簡化程式碼量,並且對後期的需求變更和維護也更加友好。
元件化思想
1.如果我們將一個頁面中所有的處理邏輯全部放在一起,處理起來就會變得非常複雜,而且不利於後續的管理以及擴充套件.
2.但如果,我們講一個頁面拆分成一個個小的功能塊,每個功能塊完成屬於自己這部分獨立的功能,那麼之後整個頁面的管理和維護就變得非常容易了.
參考:
認識元件
根元件
被掛載管理的元素塊就是一個根元件。在此根元件中可以巢狀多個子元件,根元件一般來說只需要一個
<body>
<div id='app'>
</div>
<script src="vue.js"></script>
<script>
const app = new Vue({
el:'#app',
})
</script>
</body>
子元件
子元件即是被巢狀在根元件中的元件,子元件可複用,並且資料都是相互獨立的。
子元件擁有根元件所擁有的所有屬性
元件宣告
元件的使用分三個步驟:
1.建立元件構造器
2.註冊元件
3.使用元件
1.呼叫Vue.extend()方法建立元件構造器
2.呼叫Vue.component()方法註冊元件
3.在Vue例項的作用範圍內使用元件
全域性元件
全域性元件會自動進行註冊,任何Vue
的例項都能進行使用。
使用Vue.component("name",{})
對其進行宣告並註冊。
<body> <div id='app'> <!-- 3.使用元件 --> <cpn></cpn> </div> <script src="vue.js"></script> <script> // 1.建立元件構造器物件 const cpnC = Vue.extend({ template: ` <div> <h2>第一個元件</h2> </div>` }) // 2.註冊元件 (全域性元件) Vue.component('cpn',cpnC); const app = new Vue({ el:'#app', }) </script> </body>
區域性元件
區域性元件在Vue
例項下使用components進行註冊,它只能在當前例項使用
<body>
<div id='app'>
<!-- 3.使用元件 -->
<cpn></cpn>
</div>
<script src="vue.js"></script>
<script>
// 1.建立元件構造器物件
const cpnC = Vue.extend({
template:`
<div>
<h2>第一個元件</h2>
</div>`
})
const app = new Vue({
el:'#app',
// 2.註冊元件(區域性元件)
components: {
cpn:cpnC,
}
})
</script>
</body>
元件語法糖寫法
這種寫法居多
<body>
<div id='app'>
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="vue.js"></script>
<script>
// 全域性語法糖
Vue.component('cpn2',{
template:`
<div>
<h1>第一個元件</h1>
</div>`
})
const app = new Vue({
el:'#app',
components: {
// 區域性語法糖
cpn1: {
template: `
<div>
<h1>第一個元件</h1>
</div>
`
}
}
})
</script>
</body>
元件模板抽離寫法
如果在定義元件時在template
屬性中寫HTML
程式碼,是不太友好的,你可以將模板抽離出來。
而且這個方法是用的最多。
使用<template>
標籤配合id
屬性將其作為子元件模板:(以下抽離包括全域性和區域性)
<body>
<div id='app'>
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<template id='cpn1'>
<div>
<h1>元件抽離</h1>
</div>
</template>
<template id='cpn2'>
<div>
<h1>元件抽離</h1>
</div>
</template>
<script src="vue.js"></script>
<script>
// 全域性抽離寫法
Vue.component('cpn1', {
template:'#cpn1'
})
const app = new Vue({
el:'#app',
// 區域性抽離寫法
components: {
cpn2: {
template:'#cpn2',
}
}
})
</script>
</body>
子元件中的data
上面已經說過,子元件可以擁有data/methods/computed/watch/filter
等物件。
但是需要注意的是子元件的data
必須是一個函式,且必須返回一個Object
。
這是因為每個子元件是相互獨立的,每一個元件例項都有屬於元件的狀態。
如果元件中的data
是一個物件,那麼元件進行多次呼叫的時候就會互相影響。
所以子元件中的data
必須是一個函式,因為函式呼叫時會重新申請記憶體,返回一個全新的Object
。
<body>
<div id='app'>
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<template id='cpn1'>
<div>
<h1>{{title}}</h1>
<p>{{content}}</p>
</div>
</template>
<template id='cpn2'>
<div>
<h1>{{title}}</h1>
<p>{{content}}</p>
</div>
</template>
<script src="vue.js"></script>
<script>
// 全域性註冊的元件
Vue.component('cpn1', {
template:'#cpn1',
// data必須是函式
data() {
return {
title:'我是標題11',
content:'我是內容11',
}
}
})
const app = new Vue({
el: '#app',
// 區域性註冊的元件
components: {
cpn2: {
template: '#cpn2',
// data必須是函式
data() {
return {
title: '我是標題22',
content: '我是內容22',
}
}
}
}
})
</script>
</body>
元件通訊
通訊的意義
元件之間的通訊是十分有必要的,當Vue
專案啟動後,父元件獲取到了一些資料,它將如何把這些資料分發到子元件上。
再比如,子元件上產生了一個新資料,它將如何把該資料交由父元件?
父傳子(props)
父元件向子元件傳遞資料時,則通過
props
進行傳遞。
接收值在父元件模板中採用 - 分割命名,在props
中採用駝峰式,在子元件模板中進行使用時採用與props
中同樣的命名方式
這是因為 - 分割命名方式不是Js
的合法變數名,如果props
中採用 - 來進行命名,子元件模板在使用時將查詢不到該變數名
總結一句話:如果props
中採用了駝峰標識(例如:cInfo
),那麼在父元件中使用必須用 - 來分割(例如:c-info
)
<body>
<!-- 父元件模板 -->
<div id='app'>
<!-- 定義接收:一定要使用 - 來分割,不能使用駝峰標識 -->
<cpn :c-message='message' :c-moves='moves' :c-info='info'></cpn>
</div>
<!-- 子元件模板 -->
<template id='cpn'>
<!-- 在子元件中就能使用 props 中接收的變數來渲染 -->
<div>
<h1>{{cMessage}}</h1>
<ul>
<li v-for='item in cMoves'>{{item}}</li>
</ul>
{{cMoves}}
<h2>{{cInfo.name}}</h2>
</div>
</template>
<script src="vue.js"></script>
<script>
// 父元件
const app = new Vue({
el: '#app',
data: {
message: '父元件的message',
moves:['父元件1','父元件2','父元件3'],
info: {
name:'hollow',
age:18,
height:1.88,
}
},
components: {
// 子元件
cpn: {
template: '#cpn',
// 使用props來接收父元件傳過來的三個變數
props: {
// 接受收的時候可以隨便取名
cMessage: {
type:String,
default:'null',
required:true,
},
cMoves: {
type:Array,
default:[],
},
cInfo: {
type:Object,
default:{},
}
}
}
}
})
</script>
</body>
props中的其他引數
在上述中我在props
中添加了其他引數
鍵 | 值 | 描述 |
---|---|---|
type | String、Array、Object等 | 定義接收的資料型別 |
default | 預設值 | 如果定義了default,那麼接收到的就是預設值 |
required | true/false | 定義是否必須接收引數,不寫預設false |
子傳父($emit)
1.在子元件中建立自定義函式
2.在自定義函式使用$emit
,把需要修改或者傳遞的值或方法給父元件
3.父元件接收子元件傳遞過來的自定義函式
4.父元件通過接收的值或方法來進行下一步操作
<body>
<div id='app'>
<!-- 3.父元件接收子元件傳遞過來的自定義函式 -->
<cpn @item-click='cpnClick'></cpn>
</div>
<template id='cpn'>
<div>
<!-- 1.在子元件中建立自定義函式 -->
<button v-for='item in categories' @click='btnClick(item)'>{{item.name}}</button>
</div>
</template>
<script src="vue.js"></script>
<script>
const app = new Vue({
el:'#app',
components: {
cpn: {
template:'#cpn',
data() {
return {
categories:[
{id:'aaa',name:'熱門推薦'},
{id:'bbb',name:'事件數碼'},
{id:'ccc',name:'家用家電'},
{id:'ddd',name:'電腦辦公'},
]
}
},
methods: {
// 2.自定義函式:使用$emit,把需要修改或者傳遞的值或方法給父元件
btnClick(item) {
this.$emit('item-click',item);
}
}
},
},
// 4.父元件通過接收的值或方法來進行下一步操作
methods: {
cpnClick(item) {
console.log('cpnclick',item);
}
}
})
</script>
</body>
元件訪問
父訪問子($children)
有的時候我們想直接通過父元件拿到子元件這個物件,呼叫其下面的某一個方法,可以使用$children
屬性完成操作。
<body>
<div id='app'>
<cpn></cpn>
<button @click='btnClick'>app按鈕</button>
</div>
<template id='cpn'>
<div>
<h1>我是子元件</h1>
</div>
</template>
<script src="vue.js"></script>
<script>
const app = new Vue({
el: '#app',
methods: {
btnClick() {
// 使用$children獲取子元件的內容進行操作
console.log(this.$children);
this.$children[0].show();
console.log(this.$children[0].name);
}
},
components: {
cpn: {
template:'#cpn',
methods: {
show() {
console.log('showMessage');
}
},
data() {
return {
name:'我是子元件',
}
},
}
}
})
</script>
</body>
父訪問子(refs)
上述的訪問方法並不常用,因為父元件非常依賴索引值來訪問子元件。
使用$refs
來訪問子元件就方便的多,我們需要給子元件取一個名字,再用父元件進行呼叫,這個是非常常用的手段。
<body>
<div id='app'>
<!-- 設定ref屬性 -->
<cpn ref="ref1"></cpn>
<button @click='btnClick'>app按鈕</button>
</div>
<template id='cpn'>
<div>
<h1>我是子元件</h1>
</div>
</template>
<script src="vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
},
methods: {
btnClick() {
// 通過 $refs 來獲取子元件的內容進行操作
this.$refs.ref1.show();
console.log(this.$refs.ref1.name);
}
},
components: {
cpn: {
template:'#cpn',
methods: {
show() {
console.log('showMessage');
}
},
data() {
return {
name:'我是子元件',
}
},
}
}
})
</script>
</body>
子訪問父(\(parent)和\)(root)
如果在子元件中想拿到父元件的物件,使用$parent
即可,如果存在多層巢狀,它只會拿自己上一層。
如果存在三級或以上巢狀,可以直接使用$root
來訪問根元件。與$parent
使用相同,但是它是具體的一個物件,而並非Array。
下面程式碼我一起演示了$parent
和$root
<body>
<!-- 根元件 -->
<div id='app'>
<cpn></cpn>
</div>
<!-- 子元件 -->
<template id='cpn'>
<!-- 子元件裡掛載子子元件 -->
<ccpn></ccpn>
</template>
<!-- 子子元件 -->
<template id='ccpn'>
<div>
<h2>我是子子元件</h2>
<button @click='btnClick'>按鈕</button>
</div>
</template>
<script src="vue.js"></script>
<script>
const app = new Vue({
// 根元件
el: '#app',
data: {
message:'你好啊',
name:'我是根的name',
},
components: {
// 子元件
cpn: {
template:'#cpn',
data() {
return {
name:'我是cpn的name',
}
},
// 子元件裡註冊元件,也就是子子元件
components: {
ccpn: {
template:'#ccpn',
methods: {
btnClick() {
// 通過this.$parent和this.$root訪問父元件,也可以通過.的方式獲取變數和方法
console.log('父元件是:',this.$parent);
console.log(this.$parent.name);
console.log('根元件是',this.$root);
console.log(this.$root.name);
}
},
}
}
}
}
})
</script>
</body>