Vue 实例提供了一系列属性,用于访问实例的数据、DOM 元素、组件关系等。这些属性都以 $ 开头,与用户定义的属性区分。
访问实例的数据对象:
const vm = new Vue({
data: {
message: 'Hello',
count: 0
}
})
console.log(vm.$data)
console.log(vm.$data.message)
vm.$data.message = 'World'
$data 是响应式的,修改它会触发视图更新。
访问组件接收的 props:
Vue.component('my-component', {
props: ['title', 'content'],
mounted() {
console.log(this.$props)
console.log(this.$props.title)
}
})
包含父组件传递的非 prop 属性:
Vue.component('my-input', {
props: ['value'],
inheritAttrs: false,
template: `
<div>
<input v-bind="$attrs" :value="value">
</div>
`,
mounted() {
console.log(this.$attrs)
}
})
使用示例:
<my-input
v-model="text"
placeholder="Enter text"
class="form-input"
/>
$attrs 会包含 placeholder 和 class。
包含父组件传递的事件监听器:
Vue.component('my-button', {
template: '<button v-on="$listeners"><slot></slot></button>',
mounted() {
console.log(this.$listeners)
}
})
使用示例:
<my-button @click="handleClick" @mouseenter="handleEnter">
Click me
</my-button>
访问实例的根 DOM 元素:
const vm = new Vue({
template: '<div class="container">{{ message }}</div>',
data: {
message: 'Hello'
}
}).$mount()
console.log(vm.$el)
console.log(vm.$el.className)
console.log(vm.$el.textContent)
注意:$el 在 mounted 之前是 undefined。
访问模板中的引用元素或组件:
new Vue({
template: `
<div>
<input ref="input" type="text">
<child-component ref="child"></child-component>
</div>
`,
mounted() {
this.$refs.input.focus()
this.$refs.child.someMethod()
}
})
注意:$refs 只在渲染完成后可用,不是响应式的。
访问插槽内容:
Vue.component('my-component', {
template: `
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
</div>
`,
mounted() {
console.log(this.$slots.header)
console.log(this.$slots.default)
}
})
访问作用域插槽:
Vue.component('list-component', {
template: `
<ul>
<li v-for="item in items" :key="item.id">
<slot :item="item"></slot>
</li>
</ul>
`,
props: ['items'],
mounted() {
console.log(this.$scopedSlots.default)
}
})
访问根 Vue 实例:
Vue.component('deep-child', {
mounted() {
console.log(this.$root)
console.log(this.$root.$options.name)
}
})
new Vue({
name: 'RootApp',
el: '#app'
})
访问父组件实例:
Vue.component('child', {
mounted() {
console.log(this.$parent)
this.$parent.someMethod()
}
})
注意:过度使用 $parent 会使组件耦合度增加。
访问子组件实例数组:
new Vue({
template: `
<div>
<child ref="child1"></child>
<child ref="child2"></child>
</div>
`,
mounted() {
console.log(this.$children)
this.$children.forEach(child => {
child.reset()
})
}
})
注意:refs。
访问实例的初始化选项:
const vm = new Vue({
customOption: 'foo',
data: {
message: 'Hello'
},
mounted() {
console.log(this.$options)
console.log(this.$options.customOption)
console.log(this.$options.data)
}
})
可用于访问自定义选项:
const vm = new Vue({
myOption: {
required: true,
default: 'default value'
},
created() {
const option = this.$options.myOption
console.log(option)
}
})
判断是否在服务端运行:
new Vue({
created() {
if (this.$isServer) {
console.log('Running on server')
} else {
console.log('Running on client')
}
}
})
当前组件的虚拟 DOM 节点:
Vue.component('my-component', {
mounted() {
console.log(this.$vnode)
console.log(this.$vnode.tag)
console.log(this.$vnode.data)
}
})
渲染函数的别名:
new Vue({
render(createElement) {
return createElement('div', 'Hello')
}
})
new Vue({
render() {
return this.$createElement('div', 'Hello')
}
})
const vm = new Vue({
data: {
message: 'Hello',
count: 0
}
})
const key = 'message'
console.log(vm[key])
console.log(vm.$data[key])
const vm = new Vue({
data: {
user: { name: 'John', age: 30 },
items: ['a', 'b', 'c']
}
})
Object.keys(vm.$data).forEach(key => {
console.log(key, vm.$data[key])
})
Vue.component('child', {
template: '<div>{{ parentMessage }}</div>',
computed: {
parentMessage() {
return this.$parent.message
}
}
})
new Vue({
data: {
message: 'Hello from parent'
}
})
Vue.component('form-component', {
props: ['initialData'],
data() {
return {
form: { ...this.initialData }
}
},
methods: {
reset() {
this.form = { ...this.$options.propsData.initialData }
},
submit() {
this.$emit('submit', this.$data.form)
}
}
})
Vue.component('debug-panel', {
template: `
<div class="debug-panel">
<h3>Debug Info</h3>
<pre>{{ debugInfo }}</pre>
</div>
`,
computed: {
debugInfo() {
return JSON.stringify({
data: this.$data,
props: this.$props,
attrs: this.$attrs,
$route: this.$route ? this.$route.path : 'N/A'
}, null, 2)
}
}
})
Vue.component('transparent-wrapper', {
inheritAttrs: false,
template: `
<div class="wrapper">
<input v-bind="$attrs" v-on="$listeners">
</div>
`
})
this.$refs.child.method()
this.$children[0].method()
this.message = 'new value'
this.$data.message = 'new value'
this.$emit('update', data)
this.$parent.update(data)
Vue.component('base-input', {
inheritAttrs: false,
template: `
<label>
{{ label }}
<input v-bind="$attrs" v-on="$listeners">
</label>
`,
props: ['label']
})