多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] >[success] # 基础语法知识点查缺补漏 1. **ref** :获取 **dom** , **调用组件内部方法** 2. **provide** / **inject** : **多层组件传值** >[success] ## ref **ref 可以获取 dom 元素** ,获取 **dom元素**尽量在 **mounted** 中获取,想获取那个 **dom** 就在哪个 **dom** 上添加一个 **ref** 属性然后 **定义一个名称** ,在使用时候直接 **this.$refs.定义的属性** 即可使用,如下: ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ref</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 父组件 const app = Vue.createApp({ data(){ return { count: 1 } }, mounted(){ console.log(this.$refs.count) }, template: ` <div> <div ref="count"> {{count}} </div> </div> ` }) const vm = app.mount('#root') </script> </html> ~~~ **ref** 不仅可以获取 **dom** 元素,还可以用来 **调用组件内部方法** ,如下: ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ref</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 父组件 const app = Vue.createApp({ data(){ return { count: 1 } }, mounted(){ this.$refs.common.sayHello() }, template: ` <div> <common-item ref="common" /> </div> ` }) app.component('common-item', { methods: { sayHello(){ alert('hello') }, }, template: `<div>hello world</div>` }) const vm = app.mount('#root') </script> </html> ~~~ >[success] ## provide / inject 如果有这样一个结构, **父亲组件 > 儿子组件 > 孙子组件** , **父组件调用子组件,子组件调用孙子组件** ,如果 **父组件** 想给 **孙子组件传一个值就需要一层一层的传递这个参数**,也就是 **跨层传参** ,我们通常会这样写: **index.html** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>provide / inject</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 父亲组件 const app = Vue.createApp({ data(){ return { count: 1 } }, template: ` <div> <child :count="count" /> </div> ` }) // 儿子组件 app.component('child', { props: ['count'], template: `<child-child :count="count" />` }) // 孙子组件 app.component('child-child', { props: ['count'], template: `<div>{{count}}</div>` }) const vm = app.mount('#root') </script> </html> ~~~ 这种需要 **层层的传递** ,那假如还有 **爷爷组件** ,甚至 **太爷爷组件** ,难道要 **跨越 4层 / 5层的组件** 传递来传递这个值吗,这时候我们可以使用 **vue** 提供的 **provide / inject** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>provide / inject</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 父亲组件 const app = Vue.createApp({ data(){ return { count: 3 } }, // provide: { // 1. 向下传递值(给孙子传值) // count: 2 // }, // 如果provide的值想传data中的变量,必须用函数的方式,像下面这样 provide(){ // 1. 向下传递值(给孙子传值) return { count: this.count } }, template: ` <div> <child /> <button @click="count += 1">Add</button> </div> ` }) // 儿子组件 app.component('child', { template: `<child-child />` }) // 孙子组件 app.component('child-child', { inject: ['count'], // 2. 接收上层组件传过来的值(接收爷爷传过来的值) template: `<div>{{count}}</div>` }) const vm = app.mount('#root') </script> </html> ~~~ 其实 **provide / inject** 目前还有一个问题,他的 **数据是一次性传递过去的,数据后续发生变化,孙子组件的数据不会更新** ,那么在后续讲解 **vue3.0** 中,我们会讲解如何解决这个问题。