第三章 探索组件的理念

1.组件的定义及复用性,局部组件和全局组件

组件的定义:分部分进行维护。

app.component('world',{
        template:`<div>world</div>`
    });

复用性:组件内的数据是独享的。

const app = Vue.createApp({
      template:`
       <div>
           <counter/>
           <counter/>
           <counter/>
       </div>
       `
    });
   app.component('counter',{
        data(){
            return{
                count:1
            }
        },
        template:`<div @click="count+=1">{{count}}</div>`
    });

当点击时,并不会全部都发生改变,由于组件的复用性

局部组件:定义一个常量,在父组件中首先用components进行声明,然后在模板中使用。建议首字母大写。局部组件使用时,要做一个名字和组件之间的映射对象,不写映射,Vue底层也会自动帮做映射。

 const HelloWorld={
        template:`<div>hello world</div>`
    };

    const app = Vue.createApp({
        components:{
            HelloWorld,
        },
        template:`
        <div>
            <hello-world/>
        </div>
        `
    });

全局组件:只要定义了,处处都可以用。

2.组件间传值及传值校验

组件间传值

 const app = Vue.createApp({
        data(){
            return{
                 sum1:10
            }
        },
        template:`
            <div><test :content="sum1"/></div>
        `
    });
   
   app.component('test',{
    data(){
        return{
            sum : 0,
            sum2:10,
            show:false
        }
    },

    props:['content'],

    methods:{
        handleSum(content,sum2){
            this.sum = content+sum2;
            this.show = true;
        }
    },
    template:`
    <div>sum1:{{content}}</div>
    <div>sum2:{{sum2}}</div>
    <button @click="handleSum(content,sum2)">求和</button>
    <div v-if="show">和:{{sum}}</div>
    `
   })

上述示例父组件通过:content="sum1"向子组件传递了一个变量名为content,值为sum1的变量,首先在子组件中要通过 props:[‘content’]进行接收,才可以进行使用。

传值校验

type:String,Boolean,Array,Object,Function,Symbol
required:必填
default:默认值

    props:{
        content:{
            type:Number,
            required:true,
            default:()=>{
                return 456
            }
        }
    },

3.单向数据流的理解

单向数据流的理解:子组件可以使用父组件传递过来的数据,但绝对不能修改传递过来的数据

4.Non-Props属性

Non-Props属性:父组件给子组件传递内容时,子组件不通过props接收

const app = Vue.createApp({
        template:`
        <div>
            <test message1="hello" message2="world" style="color:red"/>
        </div>     
        `
    });
   app.component('test',{
    // inheritAttrs:false,
    template:`
    <div v-bind="$attrs">Counter</div>
    <div :msg1="$attrs.message1">Counter</div>
    <div>Counter</div>
    `
   })

inheritAttrs:false,表示不接受父组件传递的Non-Props属性

5.父子组件通过事件进行通信

第一种写法:

  const app = Vue.createApp({
        data(){
            return{
                count:1
            }
        },
        methods:{
            handleAdd(count){
                this.count = count;
            }
        },
        template:`
           <test :counter="count" @add-one="handleAdd"></test>
        `
    });
    app.component('test',{
    props:['counter'],
    emits:{
        addOne:(count)=>{
            if(count < 20) return true;
            return false;
        }
    },
    methods:{
        handleAdd(){
            this.$emit('addOne',this.counter+3);
        }
    },
    template:`
        <div @click="handleAdd">{{counter}}</div>
    `
   })

子组件this.$emit(‘addOne’,this.counter+3)会向往外触发一个addOne的事件,this.counter+3为Value,在父组件中通过 @add-one进行监听,若触发,则调用handleAdd方法

第二种写法:

const Add={
        props:['modelValue'],
        methods:{
        handleAdd(){
            this.$emit('update:modelValue',this.modelValue+3);
        },
       
    },
    template:`
        <div @click="handleAdd">{{modelValue}}</div>
    `
    };
    const app = Vue.createApp({
        components:{
            Add
        },
        data(){
            return{
                count:1
            }
        },
        methods:{
            handleAdd(count){
                this.count = count;
            }
        },
        template:`
           <add v-model="count"/> 
        `
    });

6.使用插槽和具名插槽解决组件内容传递问题

使用插槽

const app = Vue.createApp({
        components:{
            Layout,List
        },
        data(){
            return{
                text:"提交"
            }
        },
        template:`
            <div>
                <myform>
                    <div>{{text}}</div>
                </myform>
                <myform>
                    <button>{{text}}</button>
                </myform>
            </div>
                
        `
    });
   app.component('myform',{
    methods:{
        handleClick(){
            alert('123')
        }
    },
    template:`
        <div>
            <input/>
            <span @click="handleClick">
                <slot></slot>
            </span>
        </div>
    `
   })

slot插槽无法绑定事件:解决方法在外层加上一层span标签在span标签中进行绑定。

具名插槽

const Layout={
        template:`
            <div>
                <slot name="header"></slot>
                <div>content</div>
                <slot name="footer"></slot>
            </div>
        `
    };

    const app = Vue.createApp({
        components:{
            Layout
        },
        template:`
            <layout>
                <template v-slot:header>
                    <div >header</div>
                </template>
                <template v-slot:footer>
                    <div >footer</div>
                </template>
            </layout>
                
        `
    });

父组件中将插槽名定义在template标签上,v-slot:header等价于#header,子组件中通过name进行引用。

作用域插槽

    const List={
        data(){
            return{
                list:[1,2,3],
            }
        },
        template:`
            <div>
               <slot v-for="item in list" :item="item"></slot>
            </div>
        `
    }

    const app = Vue.createApp({
        components:{
           List
        },
        template:`
            <list v-slot="slotProps">
                <div>{{slotProps.item}}</div>
            </list>
                
        `
    });

通过ES6解构语法可以将 v-slot=“slotProps"写成v-slot=”{item}",{{slotProps.item}}写成{item}

7.动态组件和异步组件

动态组件:通过数据改变,结合component这个标签,来随时动态切换组件的实现。

 const Layout={
        template:`
            <div>
                <input/>
            </div>
        `
    };

    const List={
        template:`
            <div>
               <span>hello world</span>
            </div>
        `
    }

    const app = Vue.createApp({
        components:{
            Layout,List
        },
        data(){
            return{
                currentItem:'list'
            }
        },
        methods:{
            handleClick() {
                if(this.currentItem == 'list'){
                    this.currentItem = 'layout';
                }else{
                    this.currentItem = 'list';
                }
            }
        },
        // <layout v-if="currentItem === 'layout'"/>
        // <list v-if="currentItem === 'list'"/>
        template:`
            <div>
                <keep-alive>
                    <component :is="currentItem"/>
                </keep-alive>
                <button @click="handleClick">切换</button>
            </div>    
        `
    });

动态组件通过 component :is="currentItem"进行实现,keep-alive用于保存切换的缓存

异步组件:异步执行某些组件的逻辑

const app = Vue.createApp({
        template:`
            <async-common-item1/>
            <async-common-item2/>
                
        `
    });

    app.component('async-common-item1',Vue.defineAsyncComponent(()=>{
        return new Promise((resolve,reject) =>{
            setTimeout(() => {
                resolve({
                    template:'<div>4秒延迟的异步组件</div>'
                })
            }, 4000);
        })
    }));

    app.component('async-common-item2',Vue.defineAsyncComponent(()=>{
        return new Promise((resolve,reject) =>{
            setTimeout(() => {
                resolve({
                    template:'<div>5秒延迟的异步组件</div>'
                })
            }, 5000);
        })
    }));

8.基础知识点查漏补缺

1.v-once

v-once:让某个元素标签只进行一次渲染

const app = Vue.createApp({
        data(){
            return{
                count:1,
            }
        },
        template:`
            <div>
                <div @click="count += 1" v-once>{{count}}</div>
            </div>
        `
    });

通过点击事件可以发显示无法自增,但实际count元素已发生自增

2.ref

ref实际上是获取dom节点/组件的语法

const app = Vue.createApp({
        data(){
            return{
                count:1,
            }
        },
        mounted(){
            console.log(this.$refs.count1);
            this.$refs.count2.sayHi();
        },
        template:`
            <div>
                <div ref="count1">{{count}}</div>
                <common-item ref="count2"></ommon-item>
            </div>   
        `
    });
     app.component('common-item',{
        methods:{
            sayHi(){
                alert('hello');
            }
        },
        template:'<div>hello</div>'
    });

mounted(),Vue中的生命周期函数,在组件渲染到页面之后立即执行的函数

3.provide/inject

provide/inject:提供数据/接收数据

const app = Vue.createApp({
        data(){
            return{
                count:1,
            }
        },
      
        provide(){
            return{
                count:this.count
            }
        },
        template:`
            <div>
                <child-child></child-child>
                <button @click="count+=1">Add</button>
            </div>
        `
    });

	app.component('child-child',{
        inject:['count'],
        template:'<div>{{count}}</div>'
    });

注意:provide只进行一次传值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值