Vue 实例
1. Vue实例
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 自动注销
}
}
})
const app = new Vue({
})
app.$mount('#app')
setTimeout(function(){
app.num += 1
}, 1000)
2. 实例属性
// Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属性的访问。
console.log(app.$data) // num : 0
// 当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象属性的访问。
console.log(app.$props) // undefined
// Vue实例使用的根 DOM 元素
console.log(app.$el) // <div>0</div>
// 用于当前 Vue 实例的初始化选项
console.log(app.$options) // {components: {…}, directives: {…}, filters: {…}, _base: ƒ, el: "#app", …}
app.$options.render = (h) => {
return h('div', {}, 'new render') // 需重新渲染时才会生效
}
// 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
console.log(app.$root)
console.log(app.$root === app) // true
// 当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。
console.log(app.$children)
// 用来访问被插槽分发的内容。每个具名插槽有其相应的属性 (例如:`slot="foo"` 中的内容将会在 `vm.$slots.foo` 中被找到)。default 属性包括了所有没有被包含在具名插槽中的节点。
console.log(app.$slots)
console.log(app.$scopedSlots)
// 一个对象,持有注册过 ref 特性的所有 DOM 元素和组件实例。
console.log(app.$refs) // {div: div}
// 当前 Vue 实例是否运行于服务器。 一般服务端渲染才会用
console.log(app.$isServer)
3. 实例方法/数据
// Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值
const unwatch = app.$watch('num', (newNum, oldNum) => {
console.log(`${newNum} : ${oldNum}`) // 1 : 0
})
unwatch() // 注销watch
// 键路径
vm.$watch('a.b.c', function (newVal, oldVal) {
// 做点什么
})
// 函数
vm.$watch(
function () {
return this.a + this.b
},
function (newVal, oldVal) {
// 做点什么
}
)
全局 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. 实例方法/事件
// 监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数会接收所有传入事件触发函数的额外参数。
app.$on('num', (a, b) => {
console.log(`emit again ${a} ${b}`)
})
app.$emit('num', 1, 2) // emit again 1 2
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
// 监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器
app.$once('num',() => {
})
5. 实例方法/生命周期
// 迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
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() // 强制重新渲染
}, 1000)
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
new Vue({
// ...
methods: {
// ...
example: function () {
// 修改数据
this.message = 'changed'
// DOM 还没有更新
this.$nextTick(function () {
// DOM 现在更新了
// `this` 绑定到当前实例
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 是在实例挂载的时候才开始执行的, 跟挂在到页面上显示的内容有关系
该钩子在服务器端渲染期间不被调用。 无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')
},
destroyed () {
console.log(this, 'destroyed')
}
})
setTimeout(()=> {
app.text += 1
}, 1000)
每次数据更新时开始执行 beforeUpdate updated
beforeUpdate 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
updated 当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 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 实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
打印 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 有关的操作一般放在 mounted 中
跟数据有关的操作可以放在 created 或者 mounted
Vue 数据绑定
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 计算属性是基于它们的依赖进行缓存的,计算属性只有在相关依赖发生改变时才会重新求值, 计算属性缓存
// 计算属性缓存
计算属性的值会被缓存, 只有在其某个反应依赖改变时才会重新计算
// 计算setter
计算属性computed 默认只有getter , 不过在需要时也可以提供一个 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 的数据开始是没有变化的, 当相应其他数据发生变化,watch数据的值才会变化
watch:{
firstName : {
handler (newName,oldName) {
this.fullName = newName + '' + this.lastName
},
immediate: true,
deep:true
}
}
数据立即执行 immediate: true
为了发现对象内部值的变化,可以在选项参数中指定 deep: true
watch 主要场景监听到某一数据变化,要去做某一个指定的变化, 需要watch 数据的变化