vue 组件化-组件通信

目录

组件分类

局部组件 建子-挂子-用子

全局组件

组件通信

父传子

子传父

平行组件

多层嵌套组件

$refs

v-model

$attrs 和 $listeners

vuex/pinia


组件分类

局部组件 建子-挂子-用子

<div id="app">
      <!-- 3.使用子组件 -->
    <App></App>
</div>
<script>
//1.创建子组件
const App = {
    //必须是一个函数
    data() {
        return {
            msg: '我是App组件'
        }
    },
    components: {
        Vcontent
    },
    template: `
    <div>
    	<Vheader></Vheader>
    	<div>
    		<Vaside />  
    		<Vcontent />
    	</div>
    </div>
    `
}
new Vue({
    el: '#app',
    data: {

    },
    components: {
        // 2.挂载子组件
        App
    }

})
</script>

全局组件

通过Vue.component(组件名,{}) 

Vue.component('Child',{
    template:`
    <div>
        <h3>我是一个子组件</h3>   
    </div>
`
})

组件通信

父传子

 子组件使用props:[]接收

Vue.component('Child',{
    template:`
    <div>
        <h3>我是一个子组件</h3>   
        <h4>{{childData}}</h4>
    </div>
`,
    props:['childData']
})
const App = {
    data() {
        return {
            msg: '我是父组件传进来的值'
        }
    },
    template: `
    <div>
    	<Child :childData = 'msg'></Child>
    </div>
	`,
    computed: {

    }
}

子传父

 子组件通过$emit()自定义事件传递给父组件

Vue.component('Child', {
    template: `
	<div>
        <h3>我是一个子组件</h3>   
        <input type="text" @input = 'handleInput'/>
	</div>
`,
    methods:{
        handleInput(e){
            //e.target.value 获取input值
            const val = e.target.value;
            //使用$emit触发子组件的事件
            this.$emit('inputHandler',val);
        }
    },
})

const App = {
    data() {
        return {
            msg: '我是父组件传进来的值',
            newVal:''
        }
    },
    methods:{
        input(value){
            this.newVal = value;
        }
    },
    template: `
    <div>
        <div class='father'>
            数据:{{newVal}}
        </div>
		<!--子组件监听事件-->
        <Child  @inputHandler = 'input'></Child>
    </div>
`,
}

平行组件

使用中央事件总线bus

bus.$emit()  bus.$on() 

使用this.$parents.$emit() this.$parents.$on()传递

const bus = new Vue();
// 中央事件总线 bus
// Vue.prototype.$bus = bus
Vue.component('B', {
    data() {
        return {
            count: 0
        }
    },
    template: `
<div>{{count}}</div>
`,
    created(){
        // $on 绑定事件
        bus.$on('add',(n)=>{
            this.count+=n;
        })
    }
})

Vue.component('A', {
    data() {
        return {

        }
    },
    template: `
    <div>
   	 <button @click='handleClick'>加入购物车</button> 
    </div>
`,
    methods:{
        handleClick(){
            // this.$parent.$emit('add', 1)
            // 触发绑定的函数 // $emit 触发事件
            bus.$emit('add',1);
        }
    }
})

多层嵌套组件

父组件 provide来提供变量,然后再子组件中通过inject来注入变量.无论组件嵌套多深

    //子组件
    const DemoChild = {
      data() {
        return {

        }
      },
      inject: ['childData'],
      template: `
        <div>
           孩子组件
           {{childData.name}}
        </div>
      `,
    }

    //中间子组件
    const SecondChild = {
      components: {
        DemoChild,
      },
    }

    //父组件
    const App ={
        data(){
            childData: {
                name: "provide提供"
            }
        },
        provide() {
            return {
              childData: this.childData
            }
        },
        components:{
             SecondChild
        }    
    }

$refs

this.$refs.name获取指定的元素或组件

在组合API中不行

<!-- ref 写在标签上时:this.$refs.名字  获取的是标签对应的dom元素
     ref 写在组件上时:这时候获取到的是 子组件(比如counter)的引用-->
    <div id="root">
        <!-- 子组件触发了事件 这里父组件(模板区里面)监听该事件 调用handleChange方法 
                                    因此handleChange方法定义在父组件的methods里面-->
        <counter ref="one" @change="handleChange"></counter>
 
        <counter ref="two" @change="handleChange"></counter>
        <div>{{total}}</div>
    </div>
 
    <script>
        Vue.component('counter', {
            template: '<div @click="handleClick"> {{number}} </div>',
            data: function() {
                return {
                    number: 0
                }
            },
            methods: {
                handleClick: function() {
                    this.number ++
                    //子组件向父组件传值  子组件被点击的时候 number+1  同时告诉外面 也即是触发一个事件
                    this.$emit('change')
                }
            },
        })
 
        var vm = new Vue({
            el: '#root',
            data: {
                total: 0
            },
            methods: {
                handleChange: function() {
                    //在此方法中计算两个数量的和  通过this.$refs.引用名字 获取两个子组件的引用
                    this.total = this.$refs.one.number +
                                    this.$refs.two.number
                }
            }
        })
    </script>
 

v-model

$attrs 和 $listeners

多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,这就有点大材小用了。所以就有了 $attrs / $listeners ,通常配合 inheritAttrs 一起使用。

$attrs:包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件。当一个组件没有声明任何 props 时,它包含所有父作用域的绑定 (class 和 style 除外)。

$listeners:包含了父作用域中的 (不含 .native 修饰符) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件。它是一个对象,里面包含了作用在这个组件上的所有事件监听器,相当于子组件继承了父组件的事件。

inheritAttrs:true 继承除props之外的所有属性;inheritAttrs:false 只继承class属性。

 father组件

<template>
   <child :name="name" :age="age" :infoObj="infoObj" @updateInfo="updateInfo" @delInfo="delInfo" />
</template>
<script>
    import Child from '../components/child.vue'

    export default {
        name: 'father',
        components: { Child },
        data () {
            return {
                name: 'Lily',
                age: 22,
                infoObj: {
                    from: '上海',
                    job: 'policeman',
                    hobby: ['reading', 'writing', 'skating']
                }
            }
        },
        methods: {
            updateInfo() {
                console.log('update info');
            },
            delInfo() {
                console.log('delete info');
            }
        }
    }
</script>

 child组件

<template>
    <grand-son :height="height" :weight="weight" @addInfo="addInfo" v-bind="$attrs" v-on="$listeners"  />
    // 通过 $listeners 将父作用域中的事件,传入 grandSon 组件,使其可以获取到 father 中的事件
</template>
<script>
    import GrandSon from '../components/grandSon.vue'
    export default {
        name: 'child',
        components: { GrandSon },
        props: ['name'],
        data() {
          return {
              height: '180cm',
              weight: '70kg'
          };
        },
        created() {
            console.log(this.$attrs); 
       // 结果:age, infoObj, 因为父组件共传来name, age, infoObj三个值,由于name被 props接收了,所以只有age, infoObj属性
            console.log(this.$listeners); // updateInfo: f, delInfo: f
        },
        methods: {
            addInfo () {
                console.log('add info')
            }
        }
    }
</script>

 grandson组件

<template>
    <div>
        {{ $attrs }} --- {{ $listeners }}
    <div>
</template>
<script>
    export default {
        ... ... 
        props: ['weight'],
        created() {
            console.log(this.$attrs); // age, infoObj, height 
            console.log(this.$listeners) // updateInfo: f, delInfo: f, addInfo: f
            this.$emit('updateInfo') // 可以触发 father 组件中的updateInfo函数
        }
    }
</script>

vuex/pinia

Vuex基本介绍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值