Components and component communication

Components and component communication

  • Any application may be abstracted into a component tree
  • Steps for component use:
    • Create component constructor
    • Registered components
    • Use components
  <div id="app"><!--注意这是vue的作用范围-->
        <my-cpn></my-cpn><!--使用组件-->
    </div>
    <script src="../practice/vue.js"></script>
    <script>
        //1、创建组件构造器对象,与创建vue对象一样也需要传入一个对象作为参数
        const cpnC = Vue.extend({
            template: ` <div id="app">
                     <h2>蔡蔡</h2>
                     <p>你好</p>
                    <p>水果</p>
                     </div>` 
        })
        //2.注册组件,Vue.component("定义的组件名字",组件构造器)
        Vue.component("my-cpn",cpnC)
        const app = new Vue({
            el: "#app",
            data: {
                message: "嘿嘿"
            }
        })
    </script>
Global components and local components
  • Global components mean that they can be used under multiple vue instances, local components add a components attribute to the vue instance object, and other instances can’t use it
Parent and child components
  • example:
<body>
    <div id="app">
        <!-- <cpn1></cpn1> 直接输出这个会报错因为该组件不是在全局VUe注册的也不是在app这个域内注册的-->
        <cpn2></cpn2>
    </div>

    <script src="./vue.js"></script>
    <script>
        //创建第一个组件构造器(子组件)
        const cpnc1 = Vue.extend({
            template: ` <div>
            <h2>我是标题1</h2>
            <p>我是内容1</p>
                     </div>`
        })
        //创建第二个组件构造器(父组件)
        const cpnc2 = Vue.extend({
            template: `<div>
            <h2>我是标题2</h2>
            <p>我是内容2</p>
            <cpn1></cpn1>
                     </div>`,
                    components:{
                        cpn1:cpnc1
                    }
                    //组件一在组件2中注册的,组件2在vue实例中注册的
        })
        const app=new Vue({
            el:"#app",
            data:{
                message:"你好"
            },
            components:{
                cpn2:cpnc2
            }
        })
    </script>
</body>
  • Separate writing of template template
    • Use the script tag,<script type="text/x-template" id="mycpn"> 用的时候在component属性里面的template:"#mycpn"
    • Use template tag<template id="mycpn">
  • The data of the component (the data in the component are separated)
    • The component is actually very much like a vue instance
    • There is a data attribute, data(){}, is a function, to return an object
  <div id="app">
        <cpn></cpn>
    </div>
    <template id="cpn">
        <div>
           <h2>
               当前计数:{
   
   {cnt}}
           </h2>
           <button @click=incre()>+</button>
           <button @click=decre()>-</button>
        </div>
    </template>
   
    <script src="../practice/vue.js"></script>
    <script>
        Vue.component('cpn',{
            template:'#cpn',
            data(){
                return{
                    cnt:0
                }
            },
            methods:{
                incre(){
                    this.cnt++
                },
                decre(){
                    this.cnt--
                }
            }
        })
        const app=new Vue({
            el:"#app",
            data:{
                message:'嘿嘿'
            }
        })
    </script>
  • So the data of the component is a function (data in the vue instance is an object), such as the counter example above, if it is a function, every time each page calls that counter component, a new cnt object will be generated, each page The data object of the counter component is different,但是如果这个时候的组建的data是一个对象而不是一个函数的话,一个页面点击了按钮,所有用这个组件的cnt都会变

The component is a single functional module. The encapsulated component cannot directly access the instance object, and the child component cannot directly access the content of the parent component
#####Parent-child component communication

  • note:

    • In a page, you need to request a lot of data from the server, but some data is displayed in the small component, but the small component will not send the network request, but the large component will pass the data to the small component
    • Because sending many network requests puts a lot of pressure on the server
  • props: (abbreviation of properties, parent to child) can achieve type restriction, the code is as follows

  • $emit event: (child to parent)
    Insert picture description here

  • important point:

    • The vue instance itself can be regarded as a parent component
    • The child component cannot directly reference the data of the parent component
  • Insert picture description here

  • Process understanding: If the child component wants to pass something to the parent component, it emits an event. This event type needs to be customized. When the template of the parent component uses a custom tag, listen for the event. After listening, go to the methods or in the parent component. Deal with the event elsewhere

  • Case

    • The first small case (but the code structure is a bit messy, and the subsequent files are more standardized with template, JS code, and styles. Vue files)
<body>
<!--父组件的模板-->
    <div id="app">
        <cpn @itemclick="cpnclick"></cpn>
        <!-- 浏览器默认的事件对象会传入event但是如果不是的话会自动传入自己的设置的那个参数此处即是event -->
    </div>

<!--子组件的模板-->
        <template id="cpn">
            <div>
                <button v-for="item in catego" @click="btnclick(item)">{
   
   {item.name}}</button>
                <!-- 存储类别父组件根据点击的子对象去请求相对应的数据 -->
            </div>
        </template>
   
    <script src="./vue.js"></script>

    <script>
        const cpn = {
            template: "#cpn",
            data() {
                return {
                    catego: [{
                        id: 1,
                        name: "热门推荐"
                    }, {
                        id: 2,
                        name: "排行榜"
                    }, {
                        id: 3,
                        name: "歌单"
                    }, {
                        id: 4,
                        name: "数字专辑"
                    }]
                }
            },
            methods:{
                btnclick(item){
                    // console.log(item);
                    this.$emit("itemclick",item)
                }//自定义事件类型点击拿到对应子对象通过发射出去给父组件该事件并且传递参数
            }
        }
        const app = new Vue({
            el: "#app",
            data: {
                message: "app1"
            },
            components:{
                cpn:cpn
            },
            methods:{
                cpnclick(item){
                    console.log('cpnclick',item);
                }
            }
        })
    </script>
</body>

Insert picture description here

  • The second case (combined with two-way binding understanding)
<body>
    <div id="app">
               <cpn :number1="num1" :number2="num2" @num1change="num1change" @num2change="num2change"/>
    </div>

    <template id="cpn">
        <div>
            <h2>props:{
   
   {number1}}</h2>
            <h2>data:{
   
   {dnumber1}}</h2>
            <!-- <input type="text" v-model="dnumber1"> -->
            <input type="text" :value="dnumber1" @input="num1input">
            <h2>props:{
   
   {number2}}</h2>
            <h2>data:{
   
   {dnumber2}}</h2>
            <!-- 两种进行比较,要修改的数据一定要放进data函数里面 -->
            <!-- <input type="text" v-model="dnumber2"> -->
            <input type="text" :value="dnumber2" @input="num2input">
        </div>
    </template>

    <script src="./vue.js"></script>
    <script>
        const app=new Vue({
            el:'#app',
            data:{
                num1:1,
                num2:0//也可以改变父组件中这个值
            },
            methods: {
                num1change(value){
                    this.num1=parseFloat(value)
                    //默认情况转换成string类型所以要进行转化用parse系列方法
                },
                num2change(value){
                    this.num2=parseFloat(value)
                }
            },
        components:{
            cpn:{
                template:'#cpn',
                props: {
                    number1:Number,
                    number2:Number
                },
            data(){
                return {
                    dnumber1:this.number1,
                    dnumber2:this.number2
                }//展示可以直接展示,但是如果要修改数据一定要放到data里面
            },
            methods:{
                num1input(){
                    this.dnumber1=event.target.value;
                    this.$emit('num1change',this.dnum1)
                },
                num2input(){
                    this.dnumber2=event.target.value;
                    this.$emit('num1change',this.dnum1)
                    //将数据的改变进行传输回去给num1 num2
                }
            }
            }
        }
    })
    </script>
</body>

Guess you like

Origin blog.csdn.net/Phoebe4/article/details/111145725
Recommended