Vue組件 本質(zhì)上是一個(gè)有預(yù)定義選項(xiàng)的Vue實(shí)例好爬,
Vue.component('todo-item',{
template:'<li>vue實(shí)例</li>',
props:['msg']
})
在其他地方使用
<todo-item></todo-item>
vues生命周期
beforeCreate() vue對(duì)象實(shí)例初始化之前
create() vue對(duì)象及時(shí)間完全初始化
beforMouted() 檢查是否任何模板可用于DOM中呈現(xiàn)
mouted() 模板準(zhǔn)備就緒 用模板數(shù)據(jù)替換DOM元素
beforeUpdate() //外部事件/用戶操作之前
update() //實(shí)際更新DOM對(duì)象
beforeDestroy() 對(duì)象破壞之前
destroyed對(duì)象破壞
備注
生命周期禁止使用箭頭函數(shù)(this指向一直向上查找會(huì)報(bào)錯(cuò))
vue中的數(shù)據(jù)是響應(yīng)式的如果數(shù)據(jù)變化他的頁面就會(huì)自動(dòng)變化,但是如果使用
var obj={foo:"bar"};
Object.freeze(obj); //阻止修改現(xiàn)有的屬性
new Vue({data:obj})
指令 帶有v- 前綴的特殊特性奶卓。作用是 當(dāng)表達(dá)式的值改變時(shí)一疯,將其長(zhǎng)生的連帶影響,響應(yīng)式地作用于DOM
修飾符
<!-- 阻止單擊事件冒泡 -->
<a v-on:click.stop="doThis"></a>
阻止默認(rèn)事件
<div v-on:click.prevent="dothat"></div>
修飾符串聯(lián)使用
<div v-on:click.stop.prevent="doThat"></div>
事件捕獲 模式
<div v-on:click.capture="doThis"></div>
只有該元素本身觸發(fā)
<div v-on:click.self="doThat"></div>
<!-- 滾動(dòng)事件的默認(rèn)行為 (即滾動(dòng)行為) 將會(huì)立即觸發(fā) -->
<!-- 而不會(huì)等待 `onScroll` 完成 -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>
按鍵修飾符
<input v-on:keyup.enter="fn">
監(jiān)聽鍵盤
<! >
計(jì)算屬性
使用計(jì)算屬性的原因:模板中放入太多的邏輯會(huì)讓模板國中難以維護(hù)
計(jì)算屬性和方法都能返回正確的結(jié)果
不同的是計(jì)算屬性的結(jié)果可以緩存夺姑,只有當(dāng)數(shù)據(jù)變化時(shí)墩邀,才會(huì)重新執(zhí)行計(jì)算,否則會(huì)緩存以前的結(jié)果
v-model
輸入框
<input v-model="message" placeholder="輸入文字">
<p>Message is:{{message}}</p>
clas 綁定
1 綁定對(duì)象
<div :class="{'obj1':obj1,'obj2':obj2}"></div>
data:{
obj1:btn,
obj2:btn1
}
2 綁定數(shù)組
<div :class="[class1,class2]"></div>
data:{
class1:'btn1',
class2:'btn2'
}
3 綁定三元表達(dá)式
<div :class="[active? active1:active2]"></div>
data:{
active:true,
active1:'active',
active2:'false'
}
4 綁定計(jì)算屬性
<div :class="classes"></div>
data:{
isActive:true,
isError:null
},
computed:{
classes(){
return {
active:this.isActive&&!isError,
'text-fail':this.error&&this.error.type==='fail'
}
}
}
5 綁定內(nèi)聯(lián)樣式
css屬性名使用駝峰或者短橫線分隔盏浙,存儲(chǔ)值為字符串形式
<div v-bind:style="{color:color,fontSize:font}"></div>
data:{
color:'red',
font:'30px'
}
組件
組件名
1 短線分隔
Vue.component('my-component',{})
2 首字母大寫
Vue.component('MyComponent',{})
全局注冊(cè)
<div id="app">
<my-component></my-component>
</div>
var vm=new Vue({
el:'#app'
})
//只能在根實(shí)例模板中使用 全局注冊(cè)的行為必須在根Vue實(shí)例(new Vue)創(chuàng)建之前執(zhí)行
Vue.component('my-component',{})
Prop
1 接收父組件傳來的參數(shù)
組件標(biāo)簽中通過<blog-post post-title="hello!"></blog-post> 傳入
2 子組件中js中的props:[postTitl]設(shè)置屬性
3 可以設(shè)置數(shù)據(jù)類型
props:{
title:String,
likes:Number,
isPublished:Boolean,
commentIds:Array,
author:Object
}
4 接收動(dòng)態(tài)賦值
動(dòng)態(tài)賦值一個(gè)變量
<blog-post v-bind:title="post.title"></blog-post>
動(dòng)態(tài)賦值一個(gè)表達(dá)式
<blog-post v-bind:title="post.title + 'by' + post.author.name"></blog-post>
5 傳入一個(gè)對(duì)象的所有屬性
post:{
id:1,
title:'nana'
}
<blog-post v-bind='post'></blog-post>
等價(jià)于
(可以用不帶參數(shù)的v-bind代替v-bind:title)
<blog-post v-bind:title="post.title" v-bind:id="post.id"></blog-post>
6 prop 為單向數(shù)據(jù)流
所有的prop都是從父組件傳到子組件眉睹,單向下行綁定荔茬,子組件不應(yīng)該更改prop數(shù)據(jù)
允許更改的方法
1 子組件作為一個(gè)本地的prop數(shù)據(jù)使用
prop:['init'],
data:function(){
return{
counter:this.init
}
}
2 數(shù)據(jù)轉(zhuǎn)換
props:['size'],
computed:{
normalizeSize:function(){
return this.size.trim().toLowerCase()
}
}
7 替換合并
如果我們從父級(jí)組件傳入的屬性會(huì)替換掉子組件原本的屬性但是如果是style class會(huì)合并起來
組件
<bootstrap-date-input>
他的模板
<input type="date" class="form-control">
我們使用此組件時(shí)
<bootstrap-date-input
data-date-picker="activated"
class="date-picker-theme-dark"
></bootstrap-date-input>
form-control,這是在組件的模板內(nèi)設(shè)置好的
date-picker-theme-dark竹海,這是從組件的父級(jí)傳入的 他的class 為 form-control date-picker-theme-dark 兩者合并
8 禁用特性繼承
inheritAttrs: true 允許繼承
inheritAttrs: false 不會(huì)把未注冊(cè)的Props呈現(xiàn)為普通的HTML屬性
$attrs 獲取除class style 以外未注冊(cè)的特性
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
自定義事件
1 命名規(guī)則 事件命不會(huì)自動(dòng)轉(zhuǎn)化大小寫慕蔚。觸發(fā)的事件命和監(jiān)聽的事件命必須一樣
監(jiān)聽事件名this.$emit('myEvent')
觸發(fā)事件名 v-on:my-event="doSomething" 不會(huì)產(chǎn)生效果
2 將原生事件綁定到組件上
在父組件中給子組件綁定一個(gè)原生的事件,就將子組件變成普通的HTML標(biāo)簽斋配,不加".native"事件無法觸發(fā)
<base-input v-on:focus.native="onFocus"></base-input>
3 $listeners
如果自定義組件名為input類型的但是他的模板根元素為label元素孔飒,這時(shí).native就會(huì)失效,$listeners屬性為一個(gè)包含組件上所有事件監(jiān)聽器的對(duì)象艰争,可以通過v-on="listeners"將所有的事件監(jiān)聽器指向這個(gè)組件的特定子元素
例如 為監(jiān)視器創(chuàng)建一個(gè)inputListeners的計(jì)算屬性
Vue.component('base-input',{
inheritAttrs:false,
props:['label','value'],
computed:{
inputListeners:function(){
var vm = this
return Object.assign({},$listeners,{input:function(event){
vm.$emit('input',event,target.value)
}})
}
}
]})
4 .sync修飾符
當(dāng)一個(gè)子組件改變了一個(gè)prop中的值時(shí)坏瞄。父組件中的值也改變
<child :foo.sync=”msg”></child>
注意
.sync修飾符不和表達(dá)式一起使用(v-bind:title.sync="doc.title +'!' ") 無效的
有多個(gè)屬性時(shí)當(dāng)做對(duì)象傳入
<text-document v-bind.sync="doc"></text-document>
插槽
1 語法
模板
<a v-bind:href="url" class="nav-link">
<slot></slot>
</a>
<navigation-link url="/profile">
Your Profile
</navigation-link>
渲染時(shí)會(huì)把<slot></slot>替換為Your Profile 插槽內(nèi)可以使HTML代碼也可以是其他組件。如果中間沒有<slot>標(biāo)簽甩卓,則該組建中的其他內(nèi)容會(huì)被拋棄
2 編譯作用域
<navigation-link url="/profile"> Logged in as {{ user.name }}</navigation-link>可以訪問相同實(shí)例屬性而不能<navigation-link> 的作用域注意父級(jí)模板里的內(nèi)容在父級(jí)作用域中編譯鸠匀;子級(jí)模板里的內(nèi)容在子作用域編譯
3 具名插槽
需要多個(gè)插槽
<div class="container">
<header>
<!-- 我們希望把頁頭放這里 -->
</header>
<main>
<!-- 我們希望把主要內(nèi)容放這里 -->
</main>
<footer>
<!-- 我們希望把頁腳放這里 -->
</footer>
</div>
解決
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
使用
v-slot指令 以參數(shù)的形式提供名稱縮寫# v-solt:header 等價(jià)于 #header
但是 v-slot只能添加在一個(gè)<template>上
<base-layout>
<templater v-slot:header>
<h1>Here might be a page title </h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p> Here's some contact info</p>
</template>
</base-layout>
4 作用域插槽
可以從子組件接收數(shù)據(jù),并定義渲染的方式
<div id="root">
<child>
<template slot-scope="props"><!--定義一個(gè)插槽猛频,該插槽必須放在template標(biāo)簽內(nèi)-->
<li>{{props.value}}</li><--!定義使用渲染方式-->
</template>
</child>
<child>
<template slot-scope="props">
<h1>{{props.value}}</h1><!--定義不同的渲染方式-->
</template>
</child>
</div>
<script>
Vue.component('child',{
data: function(){
return {
list:[1,2,3,4]
}
},
template: `<div>
<ul>
<slot v-for="value in list" :value=value>//使用slot占位
</slot>
</ul>
</div>`
})
var vm=new Vue({
el: '#root'
})
</script>
slot-scope為一個(gè)對(duì)象狮崩。對(duì)象里的數(shù)據(jù)就是子組件傳來的數(shù)據(jù)
v-slot:default slot-scope都可以接收來自子組件的數(shù)據(jù)
動(dòng)態(tài)組件
使用is特性來切換組件
<button @click="view='custom1'">custom1</button>
<button @click="view='custom2'">custom2</button>
<button @click="view='custom3'">custom3</button>
<div :is="view"></div>
<component :is="view"></div>
Vue.component('custom1',{
template:'<div>custom1</div>'
})
Vue.component('custom2',{
template:'<div>custom2</div>'
})
Vue.component('custom3',{
template:'<div>custom3</div>'
})
new Vue({
el:'#demo',
data:{
view:''
}
})
<keep-alive> 將元素動(dòng)態(tài)組件包括起來,組件會(huì)被緩存
注意被包括的組件都有自己的名字鹿寻,不論是name屬性 還是局部/全局注冊(cè)的
異步組件
定義的時(shí)候什么都不做睦柴,只有在組件渲染的時(shí)候進(jìn)行加載并緩存,以備下次訪問
Vue實(shí)現(xiàn)按需加載
異步加載的組件在打包的時(shí)候毡熏,會(huì)打包成單獨(dú)的js文件坦敌。通過ajax請(qǐng)求回來插入到HTML中。
處理邊界情況
1 每個(gè)new Vue實(shí)例的組件中痢法。根實(shí)例都可以通過$root屬性進(jìn)行訪問
new Vue({
data:{
foo:1
},
computed:{
bar:function(){
}
},
methods:{
baz:function(){}
}
})
獲取根組件的數(shù)據(jù)
this.$root.foo
寫入根組件的數(shù)據(jù)
thi.$root.foo = 2
訪問根組件的計(jì)算屬性
this.$root.bar
訪問根組件的方法
this.$root.baz()
2 ref獲取DOM
給元素或組件一個(gè)ID然后在js中調(diào)用它
<base-input ref="usernameInput"></base-input>
this.$refs.usernameInput
3 依賴注入provide inject
在父組件中使用provide定義個(gè)屬性或者方法
在他的任意子組件中通過inject接收它
父級(jí)組件提供
provide:{
foo:'bar'
}
后提組件使用inect接收屬性
var Child={
inject:['foo'],
created(){
console.log(this.foo)
}
}
4 程序化的監(jiān)聽事件監(jiān)聽
1 父組件通過props把數(shù)據(jù)傳給子組件
2 子組件可以使用$emit觸發(fā)父組件的自定義事件
5 遞歸組件
組件可以在他自己的模板中調(diào)用自己狱窘。必須有name屬性,沒有name這個(gè)屬性組件不能自己調(diào)用自己财搁,遞歸的時(shí)候需要一個(gè)條件來終止遞歸蘸炸,v-for
Vue動(dòng)畫
1 基本語法
<button @click="show=!show">
toggle
</button>
<transition name="fade">
<div v-show="show">過渡</div>
</transition>
new Vue({
el:'#demo',
data:{
show:true
}
})
css
.fade-enter-active, .fade-leave-active{
transiton:opacity 0.5s
}
.fade-enter, .fade-leave-to{
opacity:0;
}
Vue.extend(擴(kuò)展實(shí)例構(gòu)造器)
主要用來服務(wù)Vue.component用來生成組件的。
簡(jiǎn)單說在模板中遇到以該組件命名的自定義標(biāo)簽時(shí)尖奔,會(huì)自動(dòng)的調(diào)用擴(kuò)展實(shí)構(gòu)造器來生成組件搭儒,掛載到自定義元素標(biāo)簽上
Vue.componet('vue-button',{
template:'<button>按鈕</button>',
data:function(){},
compunted:{}
})
Vue.component如果傳入的普通對(duì)象內(nèi)部會(huì)自動(dòng)調(diào)用Vue.extend()生成對(duì)象組件然后通過Vue.component注冊(cè)
混入(mixins)
將一些可復(fù)用的方法屬性封裝起來再需要的組件中使用(類似于reset.css)
1 如果混入的屬性和方法與原來組件重合會(huì)與組件中的為主
2 混入對(duì)象的選項(xiàng)在元組件的選項(xiàng)之前調(diào)用
var mixins = {
created:function(){
console.log('混入對(duì)象的鉤子被調(diào)用')
}
}
new Vue({
mixins:[mixin],
created:function(){
console.log('組件鉤子被調(diào)用')
}
})
全局混入(全局注冊(cè)的混入對(duì)象)
Vue.mixins({
created:function(){
var myOption = this.$options.myOption
if(myOption){
console.log(myOption)
}
}
})
new Vue({
myOption:'hello!'
})