访问组件 & 元素(不推荐)——访问根实例-vue根实例 & 访问父组件-子组件访问父组件成员 & 访问子组件-父组件访问子组件成员 & 依赖注入-父组件提供成员,子组件注入父组件中provide提供的成员
在绝大多数情况下,我们最好不要触达另一个组件实例内部或手动操作 DOM 元素。
不过也确实在一些情况下做这些事情是合适的:
对于 demo 或非常小型的有少量组件的应用来说这是很方便的。不过这个模式扩展到中大型应用来说就不然了。因此在绝大多数情况下,我们强烈推荐使用 Vuex 来管理应用的状态。
访问根实例-vue根实例(不推荐)
- 小型应用中可以在 vue 根实例里存储共享数据
- 组件中可以通过 $root 访问根实例
$root
示例:
第一步:注册根实例
在main.js
中 注册根实例
import Vue from 'vue'
import App from './App.vue'
import Modal from './components/modal/index.js'
// 注册插件
Vue.use(Modal)
Vue.config.productionTip = false
// Vue根实例
new Vue({
render: h => h(App),
data: {
name: 'zs',
age: 18
}
}).$mount('#app')
第二步:新建demo.vue文件
//div里使用组件
{{ $root.name }} - {{ $root.age }}
<template>
<div>
<h1>1. 演示访问根组件</h1>
//$root 访问根实例
{{ $root.name }} - {{ $root.age }}
<input type="button" value="set" @click="$root.age = 100" >
<h1>2. 演示访问父组件</h1>
{{ $parent.name }} - {{ $parent.age }}
<input type="button" value="set" @click="$parent.age = 100" >
<h1>3. 演示访问子组件</h1>
<!-- $refs 只会在组件渲染完成之后生效,并且它们不是响应式的 -->
<input ref="txt" type="text">
<!-- {{ $refs.d.msg }} -->
<h1>4. 依赖注入</h1>
{{ myMsg }}
<input type="button" value="getMap" @click="getMap" >
</div>
</template>
<script>
export default {
// 依赖注入
// 注入父组件中provide提供的成员
inject: ['myMsg', 'getMap'],
created () {
console.log(this.$parent)
},
data () {
return {
msg: '我是子组件中的值'
}
},
methods: {
focus () {
this.$refs.txt.focus()
}
}
}
</script>
<style>
</style>
第三步:在App.vue入口文件中引入demo.vue文件
//script里引入组件
import Demo from ‘./components/01-demo’
//注册组件
components: {
Demo,}
<template>
<div id="app">
<demo ref="d"></demo>
<h1>3. 访问子组件</h1>
<input type="button" value="子组件" @click="handle">
<!-- 5. 封装组件 -->
<h1>5. 封装组件-传递属性</h1>
<!-- my-input是自定义组件,input/focus 都是自定义事件 -->
<my-input @input="handleInput" @focus="handleFocus" placeholder="请输入..." maxlength="5" class="my"></my-input>
<!-- 6. 动态组件和异步组件 -->
<h1>6. 动态组件和异步组件</h1>
<input type="button" value="登录" @click="componentId='Login'">
<input type="button" value="注册" @click="componentId='Register'">
<keep-alive>
<component :is="componentId"></component>
</keep-alive>
<h1>7. 模态框组件</h1>
<input type="button" value="modal" @click="showModal=true">
<!--
$event 只能在视图中使用
$event 是事件参数
v-model 等价于
v-bind:value="searchText"
v-on:input="searchText = $event"
-->
<my-modal v-model="showModal" @test="test"></my-modal>
<input type="button" value="js方法调用" @click="$modal">
</div>
</template>
<script>
import Demo from './components/01-demo'
import MyInput from './components/02-input'
// import Login from './components/03-login'
// import Register from './components/04-register'
import MyModal from './components/modal/index.vue'
export default {
name: 'app',
components: {
Demo,
MyInput,
// 异步组件
Login: () => import('./components/03-login'),
Register: () => import('./components/04-register'),
MyModal
},
data () {
return {
name: 'xxx',
age: 19,
// 导入组件的名字,是字符串形式
componentId: 'Login',
showModal: false
}
},
methods: {
// test (value) {
// },
handle () {
// this.$children -- 数组
// console.log(this)
// 组件对象
// console.log(this.$refs.d)
this.$refs.d.focus()
console.log(this.$refs.d.msg)
},
handleInput () {
console.log('handleInput')
},
handleFocus () {
console.log('handleFocus')
}
},
// 依赖注入
// 父组件中提供成员
provide () {
return {
myMsg: '演示依赖注入',
getMap () {
console.log('getMap')
}
}
}
}
</script>
<style>
</style>
访问父组件-子组件访问父组件成员(不推荐)
- 可以使用这种方式替换 prop 方式父给子传值
- 但是这种方式应该尽量避免使用,因为:如果值改变了,很难确认值是在哪里变化的
- 使用方式
$parent
父组件-App.vue文件中增加属性
data () {
return {
name: 'xxx',
age: 19,
}
子组件-01-demo.vue文件中进行演示访问父组件
//<h1> 2. 演示访问父组件</h1>
{{ $parent.name }} - {{ $parent.age }}
<input type="button" value="set" @click="$parent.age = 100" >
访问子组件-父组件访问子组件成员(不推荐)
- 获取子组件内的 DOM 元素
- 调用子组件内部的方法,例如:vant 中访问表单的方法
- 使用方式
$refs
子组件-01-demo.vue文件中进行添加文本框
//<h1>3. 演示访问子组件</h1>
// <!-- $refs 只会在组件渲染完成之后生效,并且它们不是响应式的 -->
<input ref="txt" type="text">
data () {
return {
msg: '我是子组件中的值'
}
},
methods: {
focus () {
this.$refs.txt.focus()
}
}
父组件-App.vue文件中获得焦点-访问子组件
// <h1>3. 访问子组件</h1>
<input type="button" value="子组件" @click="handle">
methods: {
// test (value) {
// },
handle () {
// this.$children -- 数组
// console.log(this)
// 组件对象
// console.log(this.$refs.d)
this.$refs.d.focus()
//获取子组件方法
console.log(this.$refs.d.msg)
},
注意
$refs
只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问$refs
。
依赖注入(不推荐)——父组件-提供成员,子组件-注入父组件中provide提供的成员
依赖注入——父组件-提供成员,子组件-注入父组件中provide提供的成员
-
如果组件嵌套比较深 (a=>b=>c=>d),并且所有后代组件都依赖于 a 组件的数据或者方法
-
此时虽然通过 $parent 也可以实现,但是比较麻烦,此时可以使用依赖注入的方式
-
使用方式
-
父组件中-App.vue文件-提供成员
// 组件的选项中添加 提供成员 provide: function () { return { getMap: this.getMap } }
-
所有子组件中-01-demo.vue文件
<h1>4. 依赖注入</h1> {{ myMsg }} <input type="button" value="getMap" @click="getMap" > // 组件的选项中自定义位置添加 注入父组件中provide提供的成员 inject: ['getMap']
-
-
注意:
- 可以把依赖注入看成大范围的 prop
- 这种方式的数据是非响应式的
- 负面影响:耦合变高,使重构变得更加困难