1. 表單綁定 v-model
表單控件在實際開發(fā)中是非常常見的渊迁。特別是對于用戶信息的提交,需要大量的表單。
Vue
中使用v-model
指令來實現(xiàn)表單元素和數(shù)據(jù)的雙向綁定月趟。
1.1 案例分析
當(dāng)我們在輸入框輸入內(nèi)容時莉测。
因為
input
中的v-model
綁定了message
,所以會實時將輸入的內(nèi)容傳遞給message
柔袁,message
發(fā)生改變呆躲。當(dāng)
message
發(fā)生改變時,因為上面我們使用Mustache
語法捶索,將message的值插入到DOM
中插掂,所以DOM
會發(fā)生響應(yīng)的改變。所以腥例,通過
v-model
實現(xiàn)了雙向的綁定辅甥。
<div id="app">
<!-- v-model 是一個雙向綁定 -->
<input type="text" v-model="message">
<h2>{{message}}</h2>
</div>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
message: ''
},
methods: {}
});
1.2 v-model 原理
-
v-model
指令就是v-click:input
和v-bind:value
指令的結(jié)合,再使用$event
中target
獲取到當(dāng)前輸入框中輸入的值院崇。
<div id="app">
<!--
v-model = v-on:input + v-bind:value
-->
<input type="text" name="username" id="username" :value="message" @input="valueChange">
<input type="text" name="email" id="email" :value="message" @input="message = $event.target.value">
<h2>{{message}}</h2>
</div>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
message: '您好啊!'
},
methods: {
valueChange(event) {
this.message = event.target.value;
}
}
});
1.3 v-model 結(jié)合 radio 類型
- 單選框的實現(xiàn)需要多個
input
使用相同的name
屬性肆氓。
<div id="app">
<label for="male">
<input type="radio" name="sex" id="male" value="1" v-model="sex">男
</label>
<label for="female">
<input type="radio" name="sex" id="female" value="0" v-model="sex">女
</label>
</div>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
sex: 1
}
});
1.4 v-model 結(jié)合CheckBox
<div id="app">
<input type="checkbox" value="籃球" name="basketball" id="basketball" v-model="hobbies">籃球
<input type="checkbox" value="羽毛球" name="badminton" id="badminton" v-model="hobbies">羽毛球
<input type="checkbox" value="毽子" name="shuttlecock" id="shuttlecock" v-model="hobbies">毽子
<input type="checkbox" value="足球" name="football" id="football" v-model="hobbies">足球
<h2>{{hobbies}}</h2>
</div>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
hobbies: []
}
});
1.5 v-model 結(jié)合select
-
select
可以實現(xiàn)單選和多選 。使用multiple
屬性底瓣。
<div id="app">
<!-- 1. 選擇一個 -->
<select name="fruit" id="fruit" v-model="fruit">
<option value="蘋果">蘋果</option>
<option value="香蕉">香蕉</option>
<option value="芒果">芒果</option>
<option value="李子">李子</option>
</select>
<h2>{{fruit}}</h2>
<br>
<br>
<br>
<!-- 2. 選擇多個 multiple 屬性-->
<select name="fruit" id="fruits" multiple v-model="fruits">
<option value="蘋果">蘋果</option>
<option value="香蕉">香蕉</option>
<option value="芒果">芒果</option>
<option value="李子">李子</option>
</select>
<h2>{{fruits}}</h2>
</div>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
fruit: '香蕉',
fruits: []
}
});
1.6 v-model 的值綁定
- 所謂的值綁定就是將數(shù)據(jù)動態(tài)的綁定到每一個操作項上谢揪。
<div id="app">
<label v-for="hobby in hobbies" :for="hobby">
<input type="checkbox" name="hobby" :id="hobby" :value="hobby" v-model="selected">{{hobby}}
</label>
<h2>您的愛好是 : {{selected}}</h2>
</div>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
hobbies: ['籃球', '足球', '羽毛球', '乒乓球', '高爾夫球'],
selected: []
}
});
1.7 v-model 修飾符的使用
lazy
: 可以讓雙向綁定的元素蕉陋,減少實時渲染次數(shù),只有當(dāng)鼠標(biāo)失去焦點或者當(dāng)用戶按下回車的時候才渲染拨扶。number
:可以將綁定的數(shù)據(jù)的數(shù)據(jù)類型轉(zhuǎn)換為number
類型凳鬓,方便一些需要使用數(shù)字的地方。trim
: 去除字符串兩邊的空格患民。
<div id="app">
<!-- 1. 使用lazy修飾符的v-model 當(dāng)輸入完成之后敲回車或者是當(dāng)鼠標(biāo)失去焦點的時候更新數(shù)據(jù) -->
<input type="text" name="username" id="username" v-model.lazy="username">
<h2>您輸入的用戶名是 : {{username}}</h2>
<!-- 2. 使用number修飾符修飾的v-model 文本框中的數(shù)據(jù)類型會轉(zhuǎn)換為string 后期不方便處理使用number修飾符的文本框文本類型是 number 的 -->
<input type="number" name="phoneNum" id="phoneNum" v-model.number="phoneNum">
<h2> 文本框的類型 : {{typeof phoneNum}} </h2>
<!--3. 使用trim 去除字符串兩邊的空格-->
<input type="text" name="content" id="content" v-model.trim="content">
<h2>{{content}}</h2>
</div>
const app = new Vue({
el: '#app',
data: {
username: '',
phoneNum: 0,
content: ''
}
});
2. 組件化
- 組件化是
Vue.js
中的重要思想,它提供了一種抽象缩举,讓我們可以開發(fā)出一個個獨立可復(fù)用的小組件來構(gòu)造我們的應(yīng)用。任何的應(yīng)用都會被抽象成一顆組件樹匹颤。
2.1 注冊組件的基本步驟
創(chuàng)建組件構(gòu)造器;
注冊組件;
使用組件仅孩。
<div id="app">
<cpn></cpn>
</div>
<script src="../../js/vue.js"></script>
// 1. 創(chuàng)建組件構(gòu)造器 使用Vue.extend 創(chuàng)建組件構(gòu)造器
const cpnC = Vue.extend({
template: `
<div>
<h1>我是標(biāo)題</h1>
<p>我是段落一</p>
<p>我是段落二</p>
</div>
`
});
// 2. 注冊組件
Vue.component('cpn', cpnC);
// 3. 掛載 app
const app = new Vue({
el: '#app',
data: {}
});
2.2 全局組件和局部組件
全局組件是使用
Vue.component('組件名稱' , 組件構(gòu)造器)
注冊的組件;局部組件時在 印蓖,
Vue({})
對象中使用components
屬性聲明的組件辽慕。
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpna></cpna>
<hr>
</div>
<div id="app2">
<cpn></cpn>
<!-- app注冊的局部組件在app中不能使用 <cpna></cpna>-->
</div>
<script src="../../js/vue.js"></script>
/**
* 全局組件可以在多個Vue的實例下面使用
*/
// 1. 使用Vue.extend 創(chuàng)建一個組件構(gòu)造器
const cpnC = Vue.extend({
template: `
<div>
<h2>我是標(biāo)題</h2>
<p>我是段落1</p>
<p>我是段落2</p>
</div>>
`
});
/**
* 局部組件構(gòu)造器聲明
*/
const cpnCa = Vue.extend({
template: `
<div>
<h2>我是局部組件的標(biāo)題</h2>
<p>我是段落1</p>
<p>我是段落2</p>
</div>>
`
});
// 2. 將組件注冊為全局組件
Vue.component('cpn', cpnC);
const app = new Vue({
el: '#app',
data: {},
components: {
cpna: cpnCa
}
});
const app2 = new Vue({
el: '#app2',
data: {},
components: {}
});
2.3 父組件和子組件
- 組件和組件之間存在層級關(guān)系,而其中一種非常重要的關(guān)系就是父子組件的關(guān)系。
2.4 注冊組件的語法糖簡寫
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
<cpn3></cpn3>
<cpn4></cpn4>
<hr>
</div>
<div id="app2">
<cpn1></cpn1>
<cpn2></cpn2>
<cpn3></cpn3>
<cpn4></cpn4>
</div>
<script src="../../js/vue.js"></script>
/**
* (一) 傳統(tǒng)方式注冊組件
*/
// 1. 創(chuàng)建組件構(gòu)造器
const cpnC1 = Vue.extend({
template: `
<div>
<h1>我是全局組件一</h1>
</div>
`
});
/**
* 注冊一個全局組件
* */
Vue.component('cpn1', cpnC1);
/**
* (二) 使用語法糖的方式注冊組件 : 主要是省去調(diào)用Vue.extend的步驟赦肃,而是可以直接使用一個對象來代替
*/
Vue.component('cpn2', {
template: `
<div>
<h1>我是全局組件二(使用語法糖方式創(chuàng)建)</h1>
</div>
`
});
/**
* 創(chuàng)建一個組件構(gòu)造器用于局部組件
*/
const cpnC4 = Vue.extend({
template: `
<div>
<h1>我是局部組件四</h1>
</div>
`
});
/**
* 掛載app
*/
const app = new Vue({
el: '#app',
data: {},
components: {
/* 創(chuàng)建局部組件 */
cpn3: {
template: `
<div>
<h1>我是局部組件三(使用語法糖方式創(chuàng)建)</h1>
</div>
`
},
cpn4: cpnC4
}
});
/**
* 掛載app2
*/
const app2 = new Vue({
el: '#app2',
data: {}
});
2.5 組件模板抽離
- 在編寫組件模板的時候可以使用溅蛉,
script
或者template
標(biāo)簽定義標(biāo)簽?zāi)0濉⑵鋸膶ο笾谐殡x出來他宛。
<div id="app">
<cpn></cpn>
<cpn1></cpn1>
</div>
<!-- 1. 抽離template模板 -->
<script type="text/x-template" id="cpn">
<div>
<h1>我是抽離的標(biāo)簽的標(biāo)題</h1>
<p>我是一個段落</p>
</div>
</script>
<!-- 2. 使用template標(biāo)簽包裹-->
<template id="cpn1">
<div>
<h1>我是抽離的標(biāo)簽的標(biāo)題使用template標(biāo)簽</h1>
<p>我是一個段落</p>
</div>
</template>
<script src="../../js/vue.js"></script>
Vue.component('cpn', {
template: '#cpn'
});
Vue.component('cpn1', {
template: '#cpn1'
});
const app = new Vue({
el: '#app',
data: {}
});
2.6 組件中可以訪問Vue實例中的數(shù)據(jù)嗎船侧?
組件是一個單獨功能模塊的封裝:這個模塊有屬于自己的
HTML
模板,也應(yīng)該有屬性自己的數(shù)據(jù)data
厅各。答案:不能镜撩。而且即使可以訪問,如果將所有的數(shù)據(jù)都放在
Vue
實例中讯检,Vue
實例就會變的非常臃腫琐鲁。結(jié)論:
Vue
組件應(yīng)該有自己保存數(shù)據(jù)的地方。
2.7 組件自己的數(shù)據(jù)存放在哪里呢?
組件對象也有一個
data
屬性(也可以有methods等屬性)人灼。只是這個data屬性必須是一個函數(shù)
围段。而且這個函數(shù)返回一個對象,對象內(nèi)部保存著數(shù)據(jù)投放。
<template id="cpn">
<div>
<h1>當(dāng)前計數(shù): {{counter}}</h1>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<template id="com">
<div>
<h1>{{title}}</h1>
</div>
</template>
<div id="app">
<!-- 組件實例 -->
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
<com></com>
</div>
<script src="../../js/vue.js"></script>
/**
* 語法糖方式注冊組件
*/
Vue.component('cpn', {
template: '#cpn',
data() {
return {
counter: 0
}
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
}
});
/**
* 使用語法糖方式注冊組件
*/
Vue.component('com', {
template: '#com',
data() {
return {
title: '我是標(biāo)題'
};
}
});
const app = new Vue({
el: '#app',
data: {}
});
2.8 為什么組件中的data是一個函數(shù)
- 如果不同組件他們共享一個共同的對象將會出大問題奈泪。
const obj = {
name: '張三',
age: 23
}
/**
* 每次調(diào)用函數(shù)返回一個對象
*/
function data() {
return obj;
}
let obj1 = data();
obj1.name = '李四';
let obj2 = data();
console.log(obj1); // {name: "李四", age: 23}
console.log(obj2); // {name: "李四", age: 23}
2.9 父子組件之間的通信
- 在開發(fā)中,往往一些數(shù)據(jù)確實需要從上層傳遞到下層灸芳,比如在一個頁面中涝桅,我們從服務(wù)器請求到了很多的數(shù)據(jù)。其中一部分?jǐn)?shù)據(jù)烙样,并非是我們整個頁面的大組件來展示的冯遂,而是需要下面的子組件進(jìn)行展示。這個時候谒获,并不會讓子組件再次發(fā)送一個網(wǎng)絡(luò)請求蛤肌,而是直接讓大組件(父組件)將數(shù)據(jù)傳遞給小組件(子組件)壁却。
如何進(jìn)行父子組件間的通信呢?Vue官方提到
父組件向子組件傳遞數(shù)據(jù) : 通過
props
向子組件傳遞數(shù)據(jù)裸准。子組件向父組件傳遞數(shù)據(jù): 通過事件向父組件發(fā)送消息展东。
props 的基本用法
- 在組件中,使用選項
props
來聲明需要從父級接收到的數(shù)據(jù)炒俱。props的值有兩種方式:
方式一:字符串?dāng)?shù)組盐肃,數(shù)組中的字符串就是傳遞時的名稱。
方式二:對象权悟,對象可以設(shè)置傳遞時的類型砸王,也可以設(shè)置默認(rèn)值等。
我們先來看一個最簡單的props傳遞:
在下面的代碼中僵芹,我直接將Vue實例當(dāng)做父組件拇派,并且其中包含子組件來簡化代碼凿跳。
- 真實的開發(fā)中件豌,
Vue
實例和子組件的通信和父組件和子組件的通信過程是一樣的控嗜。
實現(xiàn)父組件向子組件傳遞數(shù)據(jù)的步驟如下 :(使用字符串?dāng)?shù)組的方式)
第一步: 在子組件將
props
定義為一個字符串?dāng)?shù)組用于接收父組件傳遞的數(shù)據(jù)。第二步:將父組件的值和子組件定義的屬性進(jìn)行綁定疆栏。
第三步:值已經(jīng)傳遞過來了曾掂,在子組件中使用父組件的數(shù)據(jù)珠洗。
<!-- 父子組件之間的通信
1. 父組件向子組件傳通過props;
2. 子組件向父組件傳通過自定義事件;
在真實開發(fā)中许蓖,Vue實例和子組件的通信和父組件和子組件的通信過程是一樣的调衰。
-->
<div id="app">
<!-- 第二步 將父組件的值和子組件定義的屬性進(jìn)行綁定 -->
<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>
/* 父傳子通過 props */
const cpn = {
template:'#cpn',
data() {
return{
}
},
// 字符串?dāng)?shù)組寫法
// 第一步
props:['cmovies','cmessage']
}
const app = new Vue({
el: '#app',
data: {
message:'我是父組件的message',
movies:['陸小鳳傳奇之決戰(zhàn)紫禁之巔','陸小鳳傳奇之劍神一笑','陸小鳳傳奇之鳳舞九天']
},
components: {
/* 使用屬性的增強(qiáng)寫法 */
cpn
}
});
實現(xiàn)父組件向子組件傳遞數(shù)據(jù)的步驟如下 :(使用對象的方式)
props
除了使用數(shù)組的方式之外還能使用對象的方式接收父組件傳遞的數(shù)據(jù)嚎莉。當(dāng)需要對props
進(jìn)行類型驗證的時候趋箩,就需要使用對象的寫法琼懊。對象中屬性非自定義的數(shù)據(jù)類型可以使用
type
屬性驗證該屬性的數(shù)據(jù)類型哼丈,使用required
標(biāo)識該屬性是否為必須傳遞的醉旦,使用default
屬性設(shè)置默認(rèn)值桨啃。
驗證都支持如下類型:
String
车胡;Number
匈棘;Boolean
主卫;Array
:當(dāng)是數(shù)組類型的時候鹃愤,在設(shè)置默認(rèn)值時需要注意软吐,在某些版本之后不能使用default:[]
這樣的默認(rèn)值凹耙,而是需要一個函數(shù)肖抱,在函數(shù)中返回數(shù)組的默認(rèn)值 ,如 :default:() => { return []; }
或default:() => []
或者default() {return [];}
虐沥;Object
欲险;Date
;Function
槐壳;Symbol
务唐;當(dāng)我們有自定義構(gòu)造函數(shù)時枫笛,驗證也支持自定義的類型刑巧。
父組件傳遞值給子組件props屬性駝峰標(biāo)識
- 在進(jìn)行父組件傳遞數(shù)據(jù)給子組件的時候啊楚,在
props
中的屬性如果使用了駝峰標(biāo)識恭理,那么在子組件標(biāo)簽中使用該屬性的時候就需要使用橫線分隔的形式
颜价,綁定父組件傳遞的數(shù)據(jù)拍嵌。
2.10 子組件向父組件傳遞數(shù)據(jù)
子組件向父組件傳遞數(shù)據(jù)的步驟
- 第一步 : 定義一個,比如按鈕事件 將子組件的數(shù)據(jù)傳遞給父組件横辆。
<!-- 第一步 : 定義一個,比如按鈕事件 將子組件的數(shù)據(jù)傳遞給父組件 -->
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
- 第二步 : 將子組件的自定義事件發(fā)射給父組件 并傳遞攜帶的參數(shù)狈蚤。
btnClick(item) {
/* 第二步 : 將子組件的自定義事件發(fā)射給父組件 并傳遞攜帶的參數(shù) */
this.$emit('customevent', item);
}
- 第三步 : 在父組件中處理子組件自定義的事件脆侮。
<!-- 第三步 : 在父組件中處理子組件自定義的事件 -->
<cpn @customevent="getSonCpnData"></cpn>
- 第四步 : 處理觸發(fā)子組件自定義事件之后需要執(zhí)行的方法靖避。
/* 第四步 : 處理觸發(fā)子組件自定義事件之后需要執(zhí)行的方法 */
getSonCpnData(item) {
console.log(item);
}
<div id="app">
<!-- 第三步 : 在父組件中處理子組件自定義的事件 -->
<cpn @customevent="getSonCpnData"></cpn>
</div>
<template id="cpn">
<div>
<h2>我是子組件</h2>
<!-- 第一步 : 定義一個,比如按鈕事件 將子組件的數(shù)據(jù)傳遞給父組件 -->
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="../../js/vue.js"></script>
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id: 1, name: '手機(jī)數(shù)碼'},
{id: 2, name: '家用電器'},
{id: 3, name: '電腦辦公'},
{id: 4, name: '生鮮蔬菜'}
]
}
},
methods: {
btnClick(item) {
/* 第二步 : 將子組件的自定義事件發(fā)射給父組件 并傳遞攜帶的參數(shù) */
this.$emit('customevent', item);
}
}
};
/* 子組件產(chǎn)生了一些事件希望父組件知道 */
const app = new Vue({
el: '#app',
components: {
cpn
},
methods: {
/* 第四步 : 處理觸發(fā)子組件自定義事件之后需要執(zhí)行的方法 */
getSonCpnData(item) {
console.log(item);
}
}
});
2.11 父子組件通信-結(jié)合雙向綁定
需求1: 當(dāng)子組件中的
data
數(shù)據(jù)dNumber1 dNumber2
改變的時候 子組件props
中的number1 number2
也需要發(fā)生改變,利用的是v-model
的原理 是由v-on:input
和v-bind:value
組合篡九。需求2: 當(dāng)
number1
的值改變的時候 將number2
的值變?yōu)?number1
的100
倍榛臼。
<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="number" @input="dnumber1change" :value="dNumber1">
<h2>props:{{number2}}</h2>
<h2>data:{{dNumber2}}</h2>
<input type="number" @input="dnumber2change" :value="dNumber2">
</div>
</template>
<!--
1. 需求1: 當(dāng)子組件中的 data數(shù)據(jù) dNumber1 dNumber2 改變的時候 子組件 props 中的 number1 number2 也需要發(fā)生改變
1.1 利用的是 v-model的原理 是由 v-on:input 和 v-bind:value 組合
2. 需求2: 當(dāng) number1 的值改變的時候 將 number2 的值變?yōu)?number1 的 100 倍
-->
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
num1: 0,
num2: 0
},
methods: {
num1change(value) {
this.num1 = parseFloat(value);
},
num2change(value) {
this.num2 = parseFloat(value);
}
},
components: {
'cpn': {
template: '#cpn',
props: {
/* 這里的值有父組件的 num1 或 num2 決定 */
number1: Number,
number2: Number
},
data() {
return {
dNumber1: this.number1,
dNumber2: this.number2
};
},
methods: {
dnumber1change(event) {
// 從event中獲取當(dāng)前改變的值
this.dNumber1 = event.target.value;
// 發(fā)送一個自定義事件給父組件讓父組件的值發(fā)生改變
this.$emit('num1change', this.dNumber1);
this.dNumber2 = this.dNumber1 * 100;
this.$emit('num2change', this.dNumber2);
},
dnumber2change(event) {
this.dNumber2 = event.target.value;
this.$emit('num2change', this.dNumber2);
this.dNumber1 = this.dNumber2 / 100;
this.$emit('num1change', this.dNumber1);
}
}
}
}
});
2.12 父子組件通信-結(jié)合雙向綁定 (watch實現(xiàn))
<div id="app">
<cpn
:number1="num1"
:number2="num2"
@num1change="num1Change"
@num2change="num2Change"></cpn>
</div>
<template id="cpn">
<div>
<h2>props:{{number1}}</h2>
<h2>data:{{pNumber1}}</h2>
<input type="number" v-model="pNumber1">
<!--<input type="text" :value="pNumber1" @input="number1Change">-->
<h2>props:{{number2}}</h2>
<h2>data:{{pNumber2}}</h2>
<input type="number" v-model="pNumber2">
<!--<input type="text" :value="pNumber2" @input="number2Change">-->
</div>
</template>
<script src="../../js/vue.js">
const app = new Vue({
el: '#app',
data: {
num1: 0,
num2: 0
},
methods: {
num1Change(number1) {
this.num1 = parseFloat(number1);
},
num2Change(number2) {
this.num2 = parseFloat(number2);
}
},
components: {
'cpn': {
template: '#cpn',
props: {
number1: Number,
number2: Number
},
data() {
return {
pNumber1: this.number1,
pNumber2: this.number2
}
},
methods: {},
/* 用于監(jiān)視一個屬性的改變 */
watch: {
pNumber1(newValue, oldValue) {
this.pNumber2 = newValue * 100
// 子組件發(fā)送一個自定義事件給父組件
this.$emit('num1change', newValue);
},
pNumber2(newValue, oldValue) {
this.pNumber1 = newValue / 100
this.$emit('num2change', newValue);
}
}
}
}
});
watch 的使用
-
watch
: 是屬于Vue
實例的一個options
金刁。參考文檔,它可以監(jiān)控一個屬性的變化胀葱,在watch
中可以將屬性名稱作為方法名稱屬性名稱(newValue,oldValue)
抵屿,newValue
參數(shù)就是該屬性改變之后的值轧葛。watch
可以監(jiān)控data
中屬性的變化。
<div id="app">
<input type="text" v-model="number">
</div>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {
number: 123
},
watch: {
number(newValue, oldValue) {
console.log('number從' + oldValue + '變?yōu)榱? + newValue);
}
}
});
2.13 父組件直接訪問子組件使用 $children
和 $refs
-
$children
獲取到的是父組件中的所有子組件,結(jié)果是一個數(shù)組芳杏。包含所有子組件對象辟宗。$children
的缺陷:通過$children
訪問子組件時泊脐,是一個數(shù)組類型容客,訪問其中的子組件必須通過索引值缩挑。但是當(dāng)子組件過多,我們需要拿到其中一個時镜遣,往往不能確定它的索引值悲关,甚至還可能會發(fā)生變化寓辱。
-
$refs
獲取到的是一個類似Map
集合的對象秫筏。但是使用$refs
獲取之前需要在組件標(biāo)簽上使用ref
屬性指定这敬。$refs
和ref
指令通常是一起使用的崔涂。首先缭保,我們通過ref
給某一個子組件綁定一個特定的ID
艺骂。其次隆夯,通過this.$refs.ID
就可以訪問到該組件了吮廉。
<cpn ref="aaa"></cpn>
<cpn ref="bbb"></cpn>
<div id="app">
<cpn ref="aaa"></cpn>
<cpn ref="bbb"></cpn>
<button @click="btnClick">點我</button>
</div>
<template id="cpn">
<div>
<h2>{{message}}</h2>
</div>
</template>
<script src="../../js/vue.js"></script>
/* $children 可以拿到所有的子組件 */
/* $refs 拿到指定 ref 的組件 */
const app = new Vue({
el: '#app',
data: {},
methods: {
btnClick() {
// console.log(this.$children);
// console.log(this.$children[0].message);
// this.$children[0].showMessage();
console.log(this.$refs);
console.log(typeof this.$refs);
// let map = new Map();
// map.set('aaa', {name: '張三'});
// console.log(map);
console.log(this.$refs.aaa.message);
this.$refs.bbb.showMessage();
}
},
components: {
'cpn':
{
template: '#cpn',
data() {
return {
message: '我是子組件'
}
},
methods: {
showMessage() {
console.log(this.message);
}
}
}
}
});
2.14 子組件中訪問父組件 $parent
和 $root
$parent
: 可以獲取組件的父組件轴脐。$root
: 訪問的是根組件,Vue
實例恬涧。
<div id="app">
<cpn></cpn>
<hr>
</div>
<template id="cpn">
<div>
<h2>我是cpn組件</h2>
<button @click="btnClick"> cpn的按鈕</button>
<hr>
<!-- 這是定義的一個局部子組件 -->
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是cpn的子組件ccpn</h2>
<button @click="btnCcpnClick">ccpn的按鈕</button>
</div>
</template>
<script src="../../js/vue.js"></script>
const app = new Vue({
el: '#app',
data: {},
methods: {},
components: {
'cpn': {
template: '#cpn',
data() {
return {}
},
methods: {
btnClick() {
console.log(this.$parent); //
}
},
components: {
'ccpn': {
template: '#ccpn',
methods: {
btnCcpnClick() {
console.log(this.$parent); // 獲取的是其父組件對象
console.log(this.$root); // 獲取的是根組件對象
}
}
}
}
}
}
});
子組件通過$parent
訪問父組件注意事項
盡管在Vue開發(fā)中,我們允許通過
$parent
來訪問父組件提揍,但是在真實開發(fā)中盡量不要這樣做劳跃。子組件應(yīng)該盡量避免直接訪問父組件的數(shù)據(jù)刨仑,因為這樣耦合度太高了杉武。
如果我們將子組件放在另外一個組件之內(nèi),很可能該父組件沒有對應(yīng)的屬性飞涂,往往會引起問題封拧。
另外泽西,更不好做的是通過
$parent
直接修改父組件的狀態(tài)捧杉,那么父組件中的狀態(tài)將變得飄忽不定味抖,很不利于我的調(diào)試和維護(hù)灰粮。