Vue元件化開發 ->(個人學習記錄筆記)
阿新 • • 發佈:2021-07-28
@
目錄Vue
1. 元件化開發
1.1 基本使用過程
- 註冊元件的基本步驟:
- 建立元件
- 註冊元件
- 使用元件
Vue.extend()
:- 呼叫
Vue.extend()
建立的是一個元件構造器。 - 通常在建立元件構造器時,傳入
template
代表我們自定義元件的模板 - 改模板就是在使用到元件的地方,要顯示的HTML程式碼
- 呼叫
Vue.component()
:- 呼叫
Vue.component()
是將剛才的元件構造器註冊為一個元件,並且給它起一個元件的標籤名稱 - 所以需要傳遞兩個引數:1、註冊元件的標籤名 2、元件構造器
- 呼叫
- 元件必須掛載在某個Vue例項下。否則他不會生效
<div id="app"> <!-- 3.使用元件 --> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> </div> <script src="../js/vue.js"></script> <script> //1.建立愛你元件構造器物件 const cpnC = Vue.extend({ template: ` <div> <h2>我是標題</h2> <p>我是內容,哈哈哈</p> <p>我是內容,呵呵呵</p> </div>` }) //2.註冊元件 Vue.component('my-cpn', cpnC); const app = new Vue({ el: '#app', data: { message: '你好啊!' } }) </script>
1.2 全域性元件和區域性元件
- 全域性元件:在Vue例項外註冊,可以在多個Vue的例項下使用
- 區域性元件:在Vue例項內註冊,可以在其Vue的例項下使用
<div id="app2"> <cpn></cpn> </div> <div id="app"> <!-- 3.使用元件 --> <cpn></cpn> <cpn></cpn> </div> <script src="../js/vue.js"></script> <script> //1.建立愛你元件構造器物件 const cpnC = Vue.extend({ template: ` <div> <h2>我是標題</h2> <p>我是內容,哈哈哈</p> </div>` }) //2.註冊元件(全域性元件,意味著可以在多個Vue的例項下使用) // Vue.component('cpn', cpnC); const app = new Vue({ el: '#app', data: { message: '你好啊!' }, components:{ //cpn 使用元件時的標籤名(區域性元件) cpn:cpnC } }) const app2 = new Vue({ el: '#app2' }) </script>
1.3 父元件和子元件
<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
//1. 建立第一個元件
const cpnC1 = Vue.extend({
template: `
<div>
<h2>我是標題1</h2>
<p>我是內容1</p>
</div>
`
})
//2. 建立第二個元件
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是標題2</h2>
<p>我是內容2</p>
<cpn1></cpn1>
</div>`,
components:{
cpn1:cpnC1
}
})
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
},
components:{
cpn2:cpnC2
}
})
</script>
1.4 註冊元件的語法糖寫法
- 省去
Vue.extend()
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1. 全域性元件註冊的語法糖
// 1. 建立元件構造器
// const cpn1 = Vue.extend()
// 2. 註冊元件
//全域性元件
Vue.component('cpn1',{
template: `
<div>
<h2>我是標題1</h2>
<p>我是內容1</p>
</div>
`
});
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
},
//註冊區域性元件的語法糖
components:{
'cpn2':{
template: `
<div>
<h2>我是標題2</h2>
<p>我是內容2</p>
</div>
`
}
}
})
</script>
1.5 元件模板抽離
- script標籤
- template標籤
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<!--1. script標籤,注意:型別必須是text/x-template-->
<script type="text/x-template" id="cpn">
<div>
<h2>我是標題2</h2>
<p>我是內容2</p>
</div>
</script>
<!--2.template標籤-->
<template id="cpn1">
<div>
<h2>我是標題2</h2>
<p>我是內容2</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//1.註冊一個元件
Vue.component('cpn',{
template: '#cpn1'
})
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
}
})
</script>
1.6 元件中的data
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>{{counter}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn',{
template: '#cpn',
data(){
return{
counter:0
}
},
methods:{
increment(){
this.counter++;
},
decrement(){
this.counter--;
}
}
})
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
}
})
</script>
1.7 父子元件通訊
父傳子
- 方法
- 通過
props
向子元件傳遞資料 - 通過事件向父元件傳送訊息
- 通過
- Vue例項和子元件的通訊 和 父元件和子元件的通訊過程是一樣的
props
- 不要用駝峰標識 v-bind無法識別,如必須使用
:c-info="info"
元件內用駝峰cInfo
- 在元件中,使用選項props來宣告需要從父級接收到的資料。
- props的值有兩種方式:
- 方式一:字串陣列,陣列中的字串就是傳遞時的名稱
- 方式二:物件,物件可以設定傳遞時的型別,也可以設定預設值等
props資料驗證
- 支援的型別
String
Number
Boolean
Array
Object
Date
Function
Symbol
<div id="app">
<cpn :cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
<div>
<ul>
<li v-for="item in cmovies">{{item}}</li>
</ul>
<h2>{{cmessage}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//父傳子 props
const cpn = {
template: '#cpn',
// props: ['cmovies','cmessage'],
props:{
//1.型別限制
// cmovies: Array,
// cmessage: String,
//2.提供一些預設值
cmessage: {
type: String, //型別
default:'aaaaa', //預設值
required: true
},
//型別是物件或者陣列時,預設值必須是一個函式
cmovies: {
type:Array,
default() {
return []
}
}
},
data(){
return{}
},
}
const app = new Vue({
el: '#app',
data: {
message: '你好啊!',
movies:['海王','海賊王','海爾兄弟']
},
components:{
cpn,
}
})
</script>
子傳父
自定義事件
$emit
<!--父元件模板-->
<div id="app">
<cpn @item-click="cpnClick"></cpn>
</div>
<!--子元件模板-->
<template id="cpn">
<div>
<button v-for="item in categories" @click="itemClick(item)">
{{item.name}}
</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//子元件
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id: 'aaa', name: '熱門推薦'},
{id: 'bbb', name: '手機數碼'},
{id: 'ccc', name: '家用家電'},
{id: 'ddd', name: '電腦辦公'},
]
}
},
methods: {
itemClick(item) {
this.$emit('item-click',item)
// console.log(item);
}
}
}
//父元件
const app = new Vue({
el: '#app',
data: {
message: '你好啊!',
movies: ['海王', '海賊王', '海爾兄弟']
},
components: {
cpn,
},
methods: {
cpnClick(item){
console.log('aaaaa',item);
}
}
})
</script>
父子元件通訊案例
<div id="app">
<cpn :number1="num1"
:number2="num2"
@num1change="num1change"
@num2change="num2change"></cpn>
</div>
<template id="cpn">
<div>
<h2>props:{{number1}}</h2>
<h2>data:{{dnumber1}}</h2>
<!-- <input type="text" v-model="dnumber1">-->
<input type="text" :value="dnumber1" @input="num1Input">
<h2>props:{{number2}}</h2>
<h2>data:{{dnumber2}}</h2>
<!-- <input type="text" v-model="dnumber2">-->
<input type="text" :value="dnumber2" @input="num2Input">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊!',
num1:1,
num2:0
},
methods: {
num1change(value){
this.num1=parseInt(value);
},
num2change(value){
this.num2=parseInt(value);
}
},
components:{
cpn:{
template:'#cpn',
props:{
number1:Number,
number2:Number
},
data(){
return {
dnumber1:this.number1,
dnumber2:this.number2,
}
},
methods:{
num1Input(event){
this.dnumber1=event.target.value;
this.$emit('num1change', this.dnumber1);
this.dnumber2 = this.dnumber1*100;
this.$emit('num2change',this.dnumber2);
},
num2Input(event){
this.dnumber2=event.target.value;
this.$emit('num2change', this.dnumber2);
this.dnumber1 = this.dnumber2/100;
this.$emit('num1change',this.dnumber1)
},
}
}
},
})
</script>
watch監聽改變
watch:{
dnumber1(newValue){
this.dnumber2 = newValue*100;
this.$emit('num1change', newValue);
},
dnumber2(newValue){
this.dnumber1 = newValue*100;
this.$emit('num2change', newValue);
}
},
父子元件的訪問方式: $children
- 父元件訪問子元件:使用
$children
或$refs
(引用) - 子元件訪問父元件:使用
$parent
父訪問子
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick">按鈕</button>
</div>
<template id="cpn">
<div>我是子元件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
},
methods: {
btnClick(){
//1.關於$children
// console.log(this.$children);
// for(let c of this.$children){
// console.log(c.name);
// c.showMessage();
// }
//2.$refs
console.log(this.$refs);
}
},
components:{
cpn:{
template:'#cpn',
data() {
return{
name: '我是子元件的name'
}
},
methods:{
showMessage(){
console.log('showMessage');
}
}
}
}
})
</script>
子訪問父
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是cpn元件</h2>
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子元件</h2>
<button @click="btnClick">按鈕</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
},
components:{
cpn:{
template:'#cpn',
data(){
return{
name:'我的cpn元件的name'
}
},
components: {
ccpn:{
template:'#ccpn',
methods:{
btnClick(){
//1.訪問父元件
console.log(this.$parent);
console.log(this.$parent.name);
//2.訪問根元件$root
console.log(this.$root);
console.log(this.$root.message);
}
},
}
}
}
}
})
</script>
2. 元件化高階
2.1 slot 插槽
2.1.1 基本使用
- 插槽的基本使用
<slot></slot>
- 插槽的預設值
<slot>button</slot>
- 多個值同時放入到元件中,則一起組我誒替換元素
<!--1. 插槽的基本使用<slot></slot>-->
<!--2. 插槽的預設值<slot>button</slot>-->
<!--3. 多個值同時放入到元件中,則一起組我誒替換元素-->
<div id="app">
<cpn>
<button>案例</button>
</cpn>
<cpn>
<span>哈哈哈</span>
</cpn>
<cpn>
<i>哈哈哈</i>
<div>我是div元素</div>
<p>我是p元素</p></cpn>
<cpn>
<button>新按鈕</button>
</cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是元件</h2>
<p>我是元件,哈哈哈</p>
<!--設定預設值-->
<slot>
<button>預設按鈕</button>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
},
components: {
cpn: {
template: '#cpn',
}
}
})
</script>
2.1.2 具名插槽
- 多個插槽,區分通過新增
name
<div id="app">
<cpn>
<button slot="left">返回</button>
<span slot="center">標題</span>
</cpn>
</div>
<template id="cpn">
<div>
<slot name="left"><span>左邊</span></slot>
<slot name="center"><span>中間</span></slot>
<slot name="right"><span>右邊</span></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
},
components:{
cpn:{
template:'#cpn'
}
}
})
</script>
2.2 編譯作用域
<div id="app">
<cpn v-show="isShow"></cpn>
</div>
<template id="cpn">
<div>
<h2>我是子元件</h2>
<p>我是內容,哈哈哈</p>
<button v-show="isShow">按鈕</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊!',
isShow:true
},
components:{
cpn:{
template:'#cpn',
data(){
return{
isShow: true
}
}
}
}
})
</script>
2.3 作用域插槽
<div id="app">
<cpn></cpn>
<cpn>
<!--<span v-for="item in pLanguages"></span>-->
<template slot-scope="slot">
<!-- <span v-for="item in slot.data"> {{item}}- </span>-->
<span>{{slot.data.join(' - ')}}</span>
</template>
</cpn>
<cpn>
<!--<span v-for="item in pLanguages"></span>-->
<template slot-scope="slot">
<!-- <span v-for="item in slot.data"> {{item}}* </span>-->
<span>{{slot.data.join(' * ')}}</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="pLanguages">
<ul>
<li v-for="item in pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊!'
},
components:{
cpn:{
template:"#cpn",
data(){
return{
pLanguages:['JavaScript','C++','Java','C#','Python','Go','Swift']
}
}
}
}
})
</script>