Vue 實(shí)例
1. Vue實(shí)例
const app = new Vue({
el: '#app',
template: '<div ref="div">{{ num }}</div>'
data: {
num: 0
},
props: {
},
watch: {
num (newNum, oldNum) {
console.log(`${newNum} : ${oldNum}`) // 1 : 0 自動(dòng)注銷
}
}
})
const app = new Vue({
})
app.$mount('#app')
setTimeout(function(){
app.num += 1
}, 1000)
2. 實(shí)例屬性
// Vue 實(shí)例觀察的數(shù)據(jù)對象踩麦。Vue 實(shí)例代理了對其 data 對象屬性的訪問游昼。
console.log(app.$data) // num : 0
// 當(dāng)前組件接收到的 props 對象煤蹭。Vue 實(shí)例代理了對其 props 對象屬性的訪問码泛。
console.log(app.$props) // undefined
// Vue實(shí)例使用的根 DOM 元素
console.log(app.$el) // <div>0</div>
// 用于當(dāng)前 Vue 實(shí)例的初始化選項(xiàng)
console.log(app.$options) // {components: {…}, directives: {…}, filters: {…}, _base: ?, el: "#app", …}
app.$options.render = (h) => {
return h('div', {}, 'new render') // 需重新渲染時(shí)才會(huì)生效
}
// 當(dāng)前組件樹的根 Vue 實(shí)例逝变。如果當(dāng)前實(shí)例沒有父實(shí)例,此實(shí)例將會(huì)是其自己必逆。
console.log(app.$root)
console.log(app.$root === app) // true
// 當(dāng)前實(shí)例的直接子組件萍嬉。需要注意 $children 并不保證順序,也不是響應(yīng)式的腰池。
console.log(app.$children)
// 用來訪問被插槽分發(fā)的內(nèi)容尾组。每個(gè)具名插槽有其相應(yīng)的屬性 (例如:`slot="foo"` 中的內(nèi)容將會(huì)在 `vm.$slots.foo` 中被找到)。default 屬性包括了所有沒有被包含在具名插槽中的節(jié)點(diǎn)示弓。
console.log(app.$slots)
console.log(app.$scopedSlots)
// 一個(gè)對象讳侨,持有注冊過 ref 特性的所有 DOM 元素和組件實(shí)例。
console.log(app.$refs) // {div: div}
// 當(dāng)前 Vue 實(shí)例是否運(yùn)行于服務(wù)器奏属。 一般服務(wù)端渲染才會(huì)用
console.log(app.$isServer)
3. 實(shí)例方法/數(shù)據(jù)
// Vue 實(shí)例變化的一個(gè)表達(dá)式或計(jì)算屬性函數(shù)跨跨。回調(diào)函數(shù)得到的參數(shù)為新值和舊值
const unwatch = app.$watch('num', (newNum, oldNum) => {
console.log(`${newNum} : ${oldNum}`) // 1 : 0
})
unwatch() // 注銷watch
// 鍵路徑
vm.$watch('a.b.c', function (newVal, oldVal) {
// 做點(diǎn)什么
})
// 函數(shù)
vm.$watch(
function () {
return this.a + this.b
},
function (newVal, oldVal) {
// 做點(diǎn)什么
}
)
全局 Vue.set 的別名
vm.$set( target, key, value )
全局 Vue.delete 的別名囱皿。
vm.$delete( target, key )
const app = new Vue({
el: '#app',
template: '<div ref="div">{{ num }} {{ obj.a }}</div>',
data: {
num: 0,
obj: {}
},
watch: {
num (newNum, oldNum) {
console.log(`${newNum} : ${oldNum}`)
}
}
})
let i = 0
setTimeout(function(){
i++
app.$set('app.obj', 'a', i)
app.$delete('app.obj', 'a')
// app.obj.a = i
// app.$forceUpdate()
}, 1000)
4. 實(shí)例方法/事件
// 監(jiān)聽當(dāng)前實(shí)例上的自定義事件勇婴。事件可以由vm.$emit觸發(fā)≈鲂龋回調(diào)函數(shù)會(huì)接收所有傳入事件觸發(fā)函數(shù)的額外參數(shù)耕渴。
app.$on('num', (a, b) => {
console.log(`emit again ${a} $`)
})
app.$emit('num', 1, 2) // emit again 1 2
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
// 監(jiān)聽一個(gè)自定義事件齿兔,但是只觸發(fā)一次橱脸,在第一次觸發(fā)之后移除監(jiān)聽器
app.$once('num',() => {
})
5. 實(shí)例方法/生命周期
// 迫使 Vue 實(shí)例重新渲染。注意它僅僅影響實(shí)例本身和插入插槽內(nèi)容的子組件分苇,而不是所有子組件添诉。
const app = new Vue({
el: '#app',
template: '<div ref="div">{{ num }} {{ obj.a }}</div>',
data: {
num: 0,
obj: {}
},
watch: {
num (newNum, oldNum) {
console.log(`${newNum} : ${oldNum}`)
}
}
})
let i = 0
setTimeout(function(){
i++
app.obj.a = i
app.$forceUpdate() // 強(qiáng)制重新渲染
}, 1000)
將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行。在修改數(shù)據(jù)之后立即使用它组砚,然后等待 DOM 更新吻商。
它跟全局方法 Vue.nextTick 一樣,不同的是回調(diào)的 this 自動(dòng)綁定到調(diào)用它的實(shí)例上糟红。
new Vue({
// ...
methods: {
// ...
example: function () {
// 修改數(shù)據(jù)
this.message = 'changed'
// DOM 還沒有更新
this.$nextTick(function () {
// DOM 現(xiàn)在更新了
// `this` 綁定到當(dāng)前實(shí)例
this.doSomethingElse()
})
}
}
})
Vue生命周期方法
new Vue({
el: '#app',
template: '<div>{{ text }}</div>',
data: {
text: 0
},
beforeCreate () {
console.log(this, 'beforeCreate') // =>1 "beforeCreate"
},
created () {
console.log(this, 'created') // =>2 "created"
},
beforeMount () {
console.log(this, 'beforeMount') // =>3 "beforeMount"
},
mounted () {
console.log(this, 'mounted') // =>4 "mounted"
},
beforeUpdate () {
console.log(this, 'beforeUpdate')
},
updated () {
console.log(this, 'updated')
},
activated () {
console.log(this, 'activated')
},
deactivated () {
console.log(this, 'deactivated')
},
beforeDestroy () {
console.log(this, 'beforeDestroy')
},
destroyed () {
console.log(this, 'destroyed')
}
})
Ajax 操作賦值 最早也要在 created中
new Vue({
// el: '#app',
template: '<div>{{ text }}</div>',
data: {
text: 0
},
beforeCreate () {
console.log(this, 'beforeCreate') // => "beforeCreate"
},
created () {
console.log(this, 'created') // => "created"
},
beforeMount () {
console.log(this, 'beforeMount')
},
mounted () {
console.log(this, 'mounted')
},
beforeUpdate () {
console.log(this, 'beforeUpdate')
},
updated () {
console.log(this, 'updated')
},
activated () {
console.log(this, 'activated')
},
deactivated () {
console.log(this, 'deactivated')
},
beforeDestroy () {
console.log(this, 'beforeDestroy')
},
destroyed () {
console.log(this, 'destroyed')
}
})
app.$mount('#app')
beforeMount mounted 是在實(shí)例掛載的時(shí)候才開始執(zhí)行的, 跟掛在到頁面上顯示的內(nèi)容有關(guān)系
該鉤子在服務(wù)器端渲染期間不被調(diào)用艾帐。 無DOM執(zhí)行環(huán)境
const app = new Vue({
el: '#app',
template: '<div>{{ text }}</div>',
data: {
text: 0
},
beforeCreate () {
console.log(this, 'beforeCreate') // => "beforeCreate"
},
created () {
console.log(this, 'created') // => "created"
},
beforeMount () {
console.log(this, 'beforeMount') // => beforeMount
},
mounted () {
console.log(this, 'mounted') // => Mounted
},
beforeUpdate () {
console.log(this, 'beforeUpdate') // => beforeUpdate
},
updated () {
console.log(this, 'updated') // => updated
},
activated () {
console.log(this, 'activated')
},
deactivated () {
console.log(this, 'deactivated')
},
beforeDestroy () {
console.log(this, 'beforeDestroy')
},
destroyed () {
console.log(this, 'destroyed')
}
})
setTimeout(()=> {
app.text += 1
}, 1000)
每次數(shù)據(jù)更新時(shí)開始執(zhí)行 beforeUpdate updated
beforeUpdate 數(shù)據(jù)更新時(shí)調(diào)用,發(fā)生在虛擬 DOM 打補(bǔ)丁之前盆偿。這里適合在更新之前訪問現(xiàn)有的 DOM柒爸,比如手動(dòng)移除已添加的事件監(jiān)聽器。
updated 當(dāng)這個(gè)鉤子被調(diào)用時(shí)事扭,組件 DOM 已經(jīng)更新捎稚,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作
const app = new Vue({
el: '#app',
template: '<div>{{ text }}</div>',
data: {
text: 0
},
beforeCreate () {
console.log(this, 'beforeCreate') // => "beforeCreate"
},
created () {
console.log(this, 'created') // => "created"
},
beforeMount () {
console.log(this, 'beforeMount') // => beforeMount
},
mounted () {
console.log(this, 'mounted') // => Mounted
},
beforeUpdate () {
console.log(this, 'beforeUpdate') // => beforeUpdate
},
updated () {
console.log(this, 'updated') // => updated
},
activated () {
console.log(this, 'activated')
},
deactivated () {
console.log(this, 'deactivated')
},
beforeDestroy () {
console.log(this, 'beforeDestroy') // => beforeDestroy
},
destroyed () {
console.log(this, 'destroyed') // => destroyed
}
})
setTimeout(()=> {
app.text += 1
}, 1000)
setTimeout(()=> {
app.$destroy() // 銷毀
},2000)
beforeDestroy 實(shí)例銷毀之前調(diào)用。在這一步,實(shí)例仍然完全可用今野。
destroyed Vue 實(shí)例銷毀后調(diào)用葡公。調(diào)用后,Vue 實(shí)例指示的所有東西都會(huì)解綁定条霜,所有的事件監(jiān)聽器會(huì)被移除催什,所有的子實(shí)例也會(huì)被銷毀。
打印 this.$el
const app = new Vue({
el: '#app',
template: '<div>{{ text }}</div>',
data: {
text: 0
},
beforeCreate () {
console.log(this.$el, 'beforeCreate') // undefined "beforeCreate"
},
created () {
console.log(this.$el, 'created') // undefined "created"
},
beforeMount () {
console.log(this.$el, 'beforeMount') // <div id="app"></div> "beforeMount"
},
mounted () {
console.log(this.$el, 'mounted') // <div>0</div> "mounted"
},
beforeUpdate () {
console.log(this, 'beforeUpdate')
},
updated () {
console.log(this, 'updated')
},
activated () {
console.log(this, 'activated')
},
deactivated () {
console.log(this, 'deactivated')
},
beforeDestroy () {
console.log(this, 'beforeDestroy')
},
destroyed () {
console.log(this, 'destroyed')
}
})
跟 DOM 有關(guān)的操作一般放在 mounted 中
跟數(shù)據(jù)有關(guān)的操作可以放在 created 或者 mounted
Vue 數(shù)據(jù)綁定
const app = new Vue({
el: '#app',
template: `
<div>
{{ isActive ? 'active' : 'not active' }}
{{ arr.join('*') }}
{{ Date.now() }}
{{ html }}
<p v-html="html"></p>
</div>
`,
data: {
isActive: false,
arr: [1,2,3],
html: '<span>123<span>'
},
})
const app = new Vue({
el: '#app',
template: `
<div :class="{ active : !isActive}" @click="handler" :id="aaa">
<p v-html="html"></p>
</div>
`,
data: {
isActive: false,
arr: [1,2,3],
html: '<span>123<span>',
aaa: 'main'
},
methods: {
handler: function() {
console.log('123')
}
}
})
computed & watch & methods
new Vue({
el: '#app',
template: `
<div>
<span>Name: {{name}}</span>
<br/>
<span>Name: {{getName()}}</span>
<br/>
<span>Number: {{num}}</span>
<p><input type = "text" v-model="num"></p>
<p>firstName: <input type = "text" v-model="firstName"></p>
<p>lastName: <input type = "text" v-model="lastName"></p>
</div>
`,
data: {
firstName: 'yym',
lastName: 'Hello',
num: 0
},
computed: {
name () {
console.log('new Name')
return `${this.firstName} ${this.lastName}`
}
},
methods: {
getName () {
console.log('getName invoked')
return `${this.firstName} ${this.lastName}`
}
}
})
computed 計(jì)算屬性是基于它們的依賴進(jìn)行緩存的,計(jì)算屬性只有在相關(guān)依賴發(fā)生改變時(shí)才會(huì)重新求值, 計(jì)算屬性緩存
// 計(jì)算屬性緩存
計(jì)算屬性的值會(huì)被緩存, 只有在其某個(gè)反應(yīng)依賴改變時(shí)才會(huì)重新計(jì)算
// 計(jì)算setter
計(jì)算屬性computed 默認(rèn)只有g(shù)etter , 不過在需要時(shí)也可以提供一個(gè) setter
computed: {
name : {
// getter
get: function () {
return `${this.firstName} ${this.lastName}`
}
// setter
set: function (newValue) {
const name = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
},
new Vue({
el: '#app',
template: `
<div>
<span>Name: {{name}}</span>
<br/>
<span>Name: {{getName()}}</span>
<br/>
<span>fullName: {{ fullName }}</span>
<br/>
<span>Number: {{num}}</span>
<p><input type = "text" v-model="num"></p>
<p>firstName: <input type = "text" v-model="firstName"></p>
<p>lastName: <input type = "text" v-model="lastName"></p>
</div>
`,
data: {
firstName: 'yym',
lastName: 'Hello',
num: 0,
fullName: ''
},
computed: {
name () {
console.log('new Name')
return `${this.firstName} ${this.lastName}`
}
},
methods: {
getName () {
console.log('getName invoked')
return `${this.firstName} ${this.lastName}`
}
},
watch:{
firstName (newName,oldName) {
this.fullName = newName + '' + this.lastName
}
}
})
watch 的數(shù)據(jù)開始是沒有變化的, 當(dāng)相應(yīng)其他數(shù)據(jù)發(fā)生變化,watch數(shù)據(jù)的值才會(huì)變化
watch:{
firstName : {
handler (newName,oldName) {
this.fullName = newName + '' + this.lastName
},
immediate: true,
deep:true
}
}
數(shù)據(jù)立即執(zhí)行 immediate: true
為了發(fā)現(xiàn)對象內(nèi)部值的變化宰睡,可以在選項(xiàng)參數(shù)中指定 deep: true
watch 主要場景監(jiān)聽到某一數(shù)據(jù)變化,要去做某一個(gè)指定的變化, 需要watch 數(shù)據(jù)的變化