vue组件实例的作用域是相互独立的,不同组件之间的数据无法相互引用。要想跨组件引用数据,需要用到组件通信
组件通信分为
1.父与子之间的通信
2.非父与子之间的通信(兄弟、隔代、跨级)
方式一:props/$emit
父和子之间
1.父组件向子组件传递数据props
父组件:
//App.vue <template> <Child v-for="list in lists" :title="list.name" :price="list.price" :info="list.info" ></Child> </template> <script> import Child from "./components/Child.vue" export default{ components:{ Child }, data(){ return{ lists:[{name:"css",price:18,info:"学习"}] } } } </script>
子组件:
//Child.vue <template> <div class="box"> <h3>书籍:{{title}}</h3> <p>价格:{{price}}</p> <p>{{info}}</p> </div> </template> <script> export default{ props:['title','price','info'] } </script> <style> .box{ border: 1px solid #ccc; } </style>
2.子组件向父组件传递数据$emit
父组件:@自定义事件名="在父组件中定义的函数"
//App.vue <template> <Child v-for="list in lists" :title="list.name" :price="list.price" :info="list.info" @showMessage="mes" ></Child> </template> <script> import Child from "./components/Child.vue" export default{ components:{ Child }, data(){ return{ lists:[{name:"css",price:18,info:"学习"}] } }, methods:{ mes(){ alert("你查看了数据") } } } </script>
父组件:
//Child.vue <template> <div class="box"> <h3>书籍:{{title}}</h3> <p>价格:{{price}}</p> <p>{{info}}</p> <button @click="show">按钮</button> </div> </template> <script> export default{ props:['title','price','info'], methods:{ show(){ this.$emit('showMessage') } } } </script> <style> .box{ border: 1px solid #ccc; } </style>
方式二:$parent/$children
父和子之间
$parent:访问父组件实例
$children:访问子组件实例
父组件:
//App.vue <template> <span>{{msg}}</span> <Child></Child> </template> <script> import Child from "./components/Child.vue" export default{ data(){ return{ msg:"father" } }, components:{ Child }, } </script>
子组件
//Child.vue <template> <p>{{messageA}}</p> <p>父组件值为:{{fatherMes}}</p> </template> <script> export default{ data(){ return{ messageA:"son" } }, computed:{ fatherMes(){ return this.$parent.msg } } } </script>
方法三:ref/refs
父调子
如果在普通的DOM元素上使用,引用指向的就是DOM元素,如果用在子组件上,引用就是指向组件实例,可以通过实例直接调用组件的方法或访问数据
父组件:
//App.vue <template> <Child ref="son"></Child> </template> <script> import Child from './components/Child.vue' export default { components:{ Child }, mounted () { const show= this.$refs['son'].msg; console.log(show); this.$refs['son'].sayHello(); console.log("--------") const show2=this.$refs.son; console.log(show2.msg); show2.sayHello(); } } </script>
子组件:
//Child.vue <template> </template> <script> export default{ data(){ return{ msg:"son" } }, methods:{ sayHello(){ console.log('hello') } } } </script>
方法四:provide/inject
跨级
父组件通过provide提供变量,子子孙孙组件通过inject来注入变量
父组件:
//App.vue <template> <Child></Child> </template> <script> import Child from "./components/Child.vue" export default{ components:{ Child }, provide:{ msg:"fatherMessage" } } </script>
子组件:
//Child.vue <template> <div class="son"> <div>子</div> {{message}} <grandChild></grandChild> </div> </template> <script> import grandChild from "./grandChild.vue" export default{ components:{ grandChild }, inject:['msg'], data(){ return{ message:this.msg } } } </script> <style> .son{ border: 1px solid black; background-color: greenyellow; } </style>
孙组件:
//grandChild.vue <template> <div class="grandson"> <div>孙</div> {{message}} </div> </template> <script> export default{ inject:['msg'], data(){ return{ message:this.msg } } } </script> <style> .grandson{ color: black; border: 1px solid black; background-color: pink; margin-left: 15px; } </style>
方法五:eventBus
任意组件之间
1.实例化,在全局引入
//main.js import Vue from 'vue' export const EventBus=new Vue()
方法六:$attrs/$listeners
跨级之间
$attrs包含了父组件中不作为prop被识别(且获取)的attribute绑定(class和style除外);子组件还可以使用v-bind="$attrs"的形式将所有父组件传来的数据(除开已经props声明了的)传向下一级子组件,通常和interitAttrs属性一起使用
父组件:
//App.vue <template> <ChildA :A="A" :B="B" :C="C" :D="D" ></ChildA> </template> <script> import ChildA from "./components/ChildA.vue" export default{ components:{ ChildA }, data(){ return{ A:"A", B:"B", C:"C", D:"D" } } } </script>
子组件:
//ChildA.vue <template> <div class="childA"> ---------------------------- <h3>直接使用$attrs</h3> ---------------------------- <p>A:{{ A }}</p> <P>App传递到A的数据:{{ $attrs }}</P> <ChildB v-bind="$attrs"></ChildB> </div> </template> <script> import ChildB from "./ChildB.vue" export default { components:{ ChildB }, inheritAttrs: false, //关闭自动挂载到组件根元素上的没有在props声明的属性 props: { A: {}, }, created() { console.log(this.$attrs); }, }; </script> <style> .childA{ background-color: greenyellow; padding: 10px; } </style>
孙组件:
//ChildB.vue <template> <div class="childB"> ---------------------------- <h3>使用v-bind="$attrs"</h3> ---------------------------- <p>B:{{B}}</p> <p>App传递到A再传递到B的数据:{{$attrs}}</p> </div> </template> <script> export default{ inheritAttrs:false, props:{ B:{} }, created(){ console.log(this.$attrs) } } </script> <style> .childB{ background-color: pink; margin-left: 15px; padding: 10px; } </style>
’$listeners包含父组件中的(不含.native修饰器的)v-on事件监听器。可以通过v-on="$listeners"传入内部组件
方法七:localStorage/sessionStorage
任意组件
localStorage:本地存储对象,存储的数据是永久性数据,页面刷新,即使浏览器重启,除非主动删除不然存储的数据会一直存在
sessionStorage:与localStorage相似,但是只有在当前页面下有效,关闭页面或浏览器存储的数据将会清空setItem(key,value)
getItem(key)
removeItem(key) 删除单个数值,根据键值移除对应的信息
clear() 删除所有数据
key(index) 获取某个索引的key
方法八:Vuex
任意组件