Vue.js
Vue.js 源码剖析-响应式原理
VueJS中学习使用Vuex详解
Vue小技巧
vue 处理组件边界情况
Vue中循环渲染img标签中的src
Virtual DOM 的实现原理
Vue.js问答3
Vue过滤器、修饰符、动画
Vue.js 源码剖析-模板编译和组件化
模拟Vue.js响应式原理
Vue.js基础回顾
Vue.js问答2
Vue.js 源码剖析-虚拟DOM
Vuex 状态管理
Vue-Router 原理实现
Vue.js问答
Vue.js生命周期
Vue.js指令
Vue.js基础难点总结
有道无术,术尚可求。有术无道,止于术!
-
+
首页
vue 处理组件边界情况
# vue 处理组件边界情况 在vue文档中有处理组件边界情况的api: - `$root`:存储到根实例中 - `parent`/`children`,可以访问父组件、子组件的属性,也可以进行修改 - `$refs`:可以访问子组件 - 依赖注入`provide`/`inject` ## 1.$root 我们在创建`vue`实例的时候可以将数据挂载到根节点 `main.js` ```js import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App), data: { title: '根实例 - Root' }, methods: { handle () { console.log(this.title) } } }).$mount('#app') ``` 在组件中使用根实例上的属性 `01-root.vue` ```html <template> <div> <!-- 小型应用中可以在 vue 根实例里存储共享数据 组件中可以通过 $root 访问根实例 --> $root.title:{{ $root.title }} <br> <button @click="$root.handle">获取 title</button> <button @click="$root.title = 'Hello $root'">改变 title</button> </div> </template> <script> export default { } </script> <style> </style> ``` 我们通过‘改变 `title`按钮改变`title`的值,会发现页面也会随之更新,也就是说我们通过`$root`获取的值都是响应式的,我们可以在页面中修改根实例的属性。 ## 2.$parent ![](http://5coder.cn/img/1669328557_5fc062c8fbc9bd294fadfcc67f972ee7.png) `01-parent.vue` ```html <template> <div class="parent"> parent <child></child> </div> </template> <script> import child from './02-child' export default { components: { child }, data () { return { title: '获取父组件实例' } }, methods: { handle () { console.log(this.title) } } } </script> <style> .parent { border: palegreen 1px solid; } </style> ``` `02-child.vue` ```html <template> <div class="child"> child<br> $parent.title:{{ $parent.title }}<br> <button @click="$parent.handle">获取 $parent.title</button> <button @click="$parent.title = 'Hello $parent.title'">改变 $parent.title</button> <grandson></grandson> </div> </template> <script> import grandson from './03-grandson' export default { components: { grandson } } </script> <style> .child { border:paleturquoise 1px solid; } </style> ``` `03-grandson.vue` ```html <template> <div class="grandson"> grandson<br> $parent.$parent.title:{{ $parent.$parent.title }}<br> <button @click="$parent.$parent.handle">获取 $parent.$parent.title</button> <button @click="$parent.$parent.title = 'Hello $parent.$parent.title'">改变 $parent.$parent.title</button> </div> </template> <script> export default { } </script> <style> .grandson { border:navajowhite 1px solid; } </style> ``` 通过`$parent.x`可以获取父组件的属性或方法. 修改`parent`中的属性,可以发现我们引入的也发生变化,因此我们通过`parent`获取的数据是响应式的。 我们通过`props`获取的数据是不可修改,这个是两者之间的区别。 ## 3.$children ![](http://5coder.cn/img/1669328757_da1b43339f0e2741af15b0058865a8a2.png) `01-parent.vue` ```html <template> <div> <children1></children1> <children2></children2> <button @click="getChildren">获取子组件</button> </div> </template> <script> import children1 from './02-children1' import children2 from './03-children2' export default { components: { children1, children2 }, methods: { getChildren () { console.log(this.$children) console.log(this.$children[0].title) console.log(this.$children[1].title) this.$children[0].handle() this.$children[1].handle() } } } </script> <style> </style> ``` `02-children1.vue` ```html <template> <div>children1</div> </template> <script> export default { data () { return { title: 'children1 获取子组件 - title' } }, methods: { handle () { console.log(this.title) } } } </script> <style> </style> ``` `03-cildren2.vue` ```html <template> <div>children2</div> </template> <script> export default { data () { return { title: 'children2 获取子组件 - title' } }, methods: { handle () { console.log(this.title) } } } </script> <style> </style> ``` - 我们通过`$children`可以获取组件数组,所以我们需要根据下标进行取值 - 我们通过`$children`获取的属性是响应式的,若我们在父组件或子组件中修改,值都会发生改变。 - 但当我们子组件中还有子组件,我们想要获取的值嵌套层级就会很深。 - 可读性不高,因为我们需要使用下标去指定想要的组件 ## 4.$refs `01-parent.vue` ```html <template> <div> <myinput ref="mytxt"></myinput> <button @click="focus">获取焦点</button> </div> </template> <script> import myinput from './02-myinput' export default { components: { myinput }, methods: { focus () { this.$refs.mytxt.focus() this.$refs.mytxt.value = 'hello' } } // mounted () { // this.$refs.mytxt.focus() // } } </script> <style> </style> ``` `02-myinput.vue` ```html <template> <div> <input v-model="value" type="text" ref="txt"> </div> </template> <script> export default { data () { return { value: 'default' } }, methods: { focus () { this.$refs.txt.focus() } } } </script> <style> </style> ``` - `$refs` 可以放在2个位置,一个是组件上,一个是元素上,如果是放在组件上则获取的是组件信息,否则获取的是元素`dom`属性。 - `$refs` 使用的时候需要在页面加载完成才可以,比如在`mounted`生命周期才可获取 ## 5.provide/inject 可以让我们在组件嵌套比较多的时候利用`依赖注入`获取相关的属性。 - `provide`与`inject`是成对出现的 - `inject`注入到子组件中的成员不是响应式的 - 组件之间的耦合变高,组件嵌套比较多的情况下可以使用`provide`/`inject` `01-parent.vue` ```html <template> <div class="parent"> parent <child></child> </div> </template> <script> import child from './02-child' export default { components: { child }, // 在父组件进行依赖 provide () { return { title: this.title, handle: this.handle } }, data () { return { title: '父组件 provide' } }, methods: { handle () { console.log(this.title) } } } </script> <style> .parent { border: palegreen 1px solid; } </style> ``` `02-child.vue` ```html <template> <div class="child"> child<br> title:{{ title }}<br> <button @click="handle">获取 title</button> <button @click="title='xxx'">改变 title</button> <grandson></grandson> </div> </template> <script> import grandson from './03-grandson' export default { components: { grandson }, // 在子组件注入 inject: ['title', 'handle'] } </script> <style> .child { border:paleturquoise 1px solid; } </style> ``` `03-grandson.vue` ```html <template> <div class="grandson"> grandson<br> title:{{ title }}<br> <button @click="handle">获取 title</button> <button @click="title='yyy'">改变 title</button> </div> </template> <script> export default { // 在子组件注入 inject: ['title', 'handle'] } </script> <style> .grandson { border:navajowhite 1px solid; } </style> ``` ## 6.$attrs/$listeners `01-parent.vue` ```html <template> <div> <!-- <myinput required placeholder="Enter your username" class="theme-dark" data-test="test"> </myinput> --> <myinput required placeholder="Enter your username" class="theme-dark" @focus="onFocus" @input="onInput" data-test="test"> </myinput> <button @click="handle">按钮</button> </div> </template> <script> import myinput from './02-myinput' export default { components: { myinput }, methods: { handle () { console.log(this.value) }, onFocus (e) { console.log(e) }, onInput (e) { console.log(e.target.value) } } } </script> <style> </style> ``` `02-myinput.vue` ```html <template> <!-- 1. 从父组件传给自定义子组件的属性,如果没有 prop 接收 会自动设置到子组件内部的最外层标签上 如果是 class 和 style 的话,会合并最外层标签的 class 和 style --> <!-- <input type="text" class="form-control" :placeholder="placeholder"> --> <!-- 2. 如果子组件中不想继承父组件传入的非 prop 属性,可以使用 inheritAttrs 禁用继承 然后通过 v-bind="$attrs" 把外部传入的非 prop 属性设置给希望的标签上 但是这不会改变 class 和 style --> <!-- <div> <input type="text" v-bind="$attrs" class="form-control"> </div> --> <!-- 3. 注册事件 --> <!-- <div> <input type="text" v-bind="$attrs" class="form-control" @focus="$emit('focus', $event)" @input="$emit('input', $event)" > </div> --> <!-- 4. $listeners --> <div> <input type="text" v-bind="$attrs" class="form-control" v-on="$listeners" > </div> </template> <script> export default { // props: ['placeholder', 'style', 'class'] // props: ['placeholder'] inheritAttrs: false } </script> <style> </style> ```
Vue
Leo
2022年11月25日 06:45
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码