Vue.js学习笔记 02、Vue组件篇笔记(上)

举报
长路 发表于 2022/11/28 21:49:40 2022/11/28
【摘要】 文章目录前言一、全局组件子组件应用组件优点:组件的可复用性全局组件缺点描述二、局部组件创建与注册局部组件(认识components属性)局部组件的默认规定(组件名称首字母全都大写)三、父子组件的传值(静态、动态)3.1、静态传值(name="技小胖")3.2、动态传值(v-bind:xx="xx"配合子组件中的props数组接收)动态传递值动态传递函数3.3、三种校验方式①类型校验(props需要

@[toc]

前言

本篇博客是在学习技术胖-Vue3.x从零开始学-第一季 基础语法篇过程中记录整理的笔记,若文章中出现相关问题,请指出!

  • 当前该链接失效了,有需要的小伙伴可以去b站或者技术胖官网去找相应的视频与笔记。

所有博客文件目录索引:博客目录索引(持续更新)


一、全局组件

子组件应用

<body>
  <div id="app"></div>
</body>

<script>
  //根组件(全局组件)
  const app = Vue.createApp({
    //直接应用两个自组件
    template: `
        <website />
        <describe />
    `
  });

  //子组件
  app.component('website', {
    template: ` <h2>JSPang.com</h2>`
  })
  app.component('describe', {
    template: ` <h2>技术胖的博客</h2>`
  })

  app.mount("#app");
</script>

image-20210702155257174


组件优点:组件的可复用性

优点:组件与组件之间互不干扰,相互独立。

<body>
  <div id="app"></div>
</body>

<script>
  //根组件
  const app = Vue.createApp({
    //复用多个组件
    template: `
        <m-count />
        <m-count />
        <m-count />
    `
  });

  //子组件(全局组件)
  app.component('m-count', {
    data() {
      return {
        count: 0
      }
    },
    methods: {
      addFun() {
        this.count++;
      }
    },
    template: `
      <sapn>{{count}}</sapn>
      <button @click="addFun()">增加</button>
      <br/>
    `
  })

  app.mount("#app");
</script>

GIF

全局组件缺点描述

一旦定义了,就会占用系统资源,它是一直存在的,你在任何地方都可以使用这个全局组件,对性能产生影响。

全局组件(通过vue实例调用component())的概括:只要定义了,处处可以使用,性能不高,但是使用起来简单。



二、局部组件

创建与注册局部组件(认识components属性)

创建局部组件:直接使用一个对象{}来表示。

注册局部组件:需要配合传入到components对象属性中。

示例:

<body>
  <div id="app"></div>
</body>
<script>
  //1、创建局部组件:直接在一个对象中设置参数
  const counter = {
    data() {
      return {
        count: 0
      }
    },
    template: `<div>{{count}}<button @click="count++">增加1</button></div>`
  };

  const app = Vue.createApp({
    //2、注册局部组件,其完整写法:components: { counter:counter },前面一个是设置的别名,后一个是实际局部组件名称
    //下面我演示别名的写法,若是不使用别名使用components: { counter }即可!!!
    components: { changlu: counter },
    template: `
        <h2>JSPang.com</h2>
        <changlu />
    `
  });

  const vm = app.mount("#app")

</script>

image-20210702161059779



局部组件的默认规定(组件名称首字母全都大写)

对于组件的名称采用全部首字母大写(驼峰命名法),示例如下:

const XieDaJiao = {
    template: `<h2>谢大脚</h2>`
}


三、父子组件的传值(静态、动态)

父子组件的传值,包括静态传值和动态传值。

3.1、静态传值(name=“技小胖”)

静态传值

核心:直接在标签中使用name="技小胖",该种方式vue会进行自动解析并传入到props数组中。

<body>
  <div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    //1、通过属性name传入到子组件中
    template: `
        <h2>JSPang.com</h2>
        <Son name="技小胖" />
    `
  });

  app.component('Son', {
    //2、通过使用props数组形式根将值接收到name属性里
    props: ['name'],
    template: `<div>{{name}} div </div>`
  })

  const vm = app.mount("#app");
</script>

image-20210702161748172

效果:动态传值使用props属性接收后,对应的标签中不会有该键值了!



3.2、动态传值(v-bind:xx="xx"配合子组件中的props数组接收)

动态传递值

动态传值

将这个可改变的动态值放置在data对象里,之后使用v-bind动态从data对象中找到属性值并赋值给指定属性:

<body>
  <div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data() {
      return {
        //在data对象中包含一个可修改的属性值(动态的)
        name: "cl"
      }
    },
    //1、绑定data对象中的name值也就是cl赋值到name参数并传递到全局组件中
    template: `
        <h2>JSPang.com</h2>
        <Son v-bind:name="name" />
    `
  })

  app.component('Son', {
    //2、同样使用name属性来进行接收这个属性值
    props: ['name'],
    template: `
        <h2>JSPang.com</h2>
        <div>{{name}}</div>
    `
  })
  const vm = app.mount("#app");
</script>

GIF

注意点:静态传值一定传的是字符串string,而动态传值是根据data对象中的属性来决定!!!



动态传递函数

动态传递函数:本质与上面传递值相同,都是传递的data对象里的值。

示例:

<body>
  <div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data() {
      return {
        appFun: () => alert("我是根组件的appFun()方法")
      }
    },
    //1、还是老样子,编写v-bind:appFun = "appFun"来绑定对应data对象中的属性进行动态传函数
    template: `
        <h2>JSPang.com</h2>
        <Son :appFun="appFun" />
    `
  })

  app.component('Son', {
    //2、接收该函数
    props: ['appFun'],
    methods: {
      divClick() {
        //3、调用传入进行的函数
        this.appFun();
      }
    },
    //为标签添加点击事件来间接调用动态传入的父组件的函数
    template: `
        <h2>JSPang.com</h2>
        <div @click="divClick()">点我试试</div>
    `
  })
  const vm = app.mount("#app");
</script>

GIF



3.3、三种校验方式

①类型校验(props需要写成{}形式)

此时props需要写成{}形式,key为得到的数据,value表示需要校验的值:这种方式只是会在console中报出黄色警告信息,依旧还是将值传递过来的!

  • Vue支持的校验类型包括:String、Boolean、Array、Object、Function和Symbol。

效果:仅仅有警告信息,传递依旧会执行。

app.component('Son', {
    //校验name是否为string类型
    props: {
        name: String
    },
    template: `<div>{{name}} div </div>`
})

image-20210702165344713



②必填校验与默认值设置(required与default)

required

required(布尔值true,false):必须传递参数,若是设置了类型参数就必须要校验指定传递的类型。

效果:会报黄色警告信息,传递空值也就是阻止传递,程序也会依旧运行!

注意:与default同时存在时,default失效!

示例

const app = Vue.createApp({
    data() {
        return {
            name: 123
        }
    },
	//进行传递值,只是传递的是number类型
    template: `
        <h2>JSPang.com</h2>
        <Son :name="name"/>
     `
})

app.component('Son', {
    //包含requred属性进行校验是否为String类型,不是就会阻止传递进来
    props: {
        name: {
            type: String,
            // required: false
            default: 'i am changlu'
        }
    },
    template: `<div>{{name}} div </div>`
})

default

default(默认值):没有传递指定参数会设置默认值给指定参数。

效果:当没有传递过来指定值时,就会使用默认参数(没有required情况下)。

示例:

const app = Vue.createApp({
    data() {
        return {
            name: 123
        }
    },
	//没有进行传递值
    template: `
        <h2>JSPang.com</h2>
        <Son />
     `
})

app.component('Son', {
    //由于name没有接受到传递值并且没有required,就会使用default默认值
    props: {
        name: {
            type: String,
            default: 'i am changlu'
        }
    },
    template: `<div>{{name}} div </div>`
})

image-20210702170417813



③精准校验(validator)

validator:精准校验是一个函数:通过布尔类型返回值来表示校验失败还是通过。

  • true:表示通过校验。
  • false:表示没有通过校验,仅仅在console上报警告信息,传值同样成功

示例:

<body>
  <div id="app"></div>
</body>

<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data() {
      return {
        name: 'xxxSPan'
      }
    },
    template: `
            <h2>JSPang.com</h2>
            <Son :name="name"/>
        `
  })

  app.component('Son', {
    props: {
      name: {
        type: String,
        //validator属性是一个函数用于进行简单校验,根据返回值来表示是否通过
        //与default不会有任何联系,记住default只是没有传递值的时候进行设置默认值的
        validator: function (value) {
          console.log(value.search("JSPang"))
          return value.search("JSPang") != -1
        },
        default: 'JSPang.com'
      }
    },
    template: `<div>{{name}} div </div>`
  })

  const vm = app.mount("#app")
</script>

image-20210702172827125



四、单项数据流

4.1、父子组件传递属性补充

①以对象形式传递多个参数

之前仅仅学习了单个值单个值传递,若是参数有多个在父组件标签中需要写大量的绑定传值,造成冗余。

效果:将要传递的多个参数封装到一个对象中传递即可!

image-20210707125554811

示例

<body>

  <div id="app">
  </div>

  <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          //1、将多个参数绑定至一个对象
          params: {
            content: 'xxx内容',
            a: 'a',
            b: 'b'
          }
        }
      },
      //2、使用v-bind='xx',来绑定某个对象进行传值
      template: `
          <exerTab v-bind="params" />
          `
    });

    app.component('exerTab', {
      //3、可直接使用对象内部的属性名来接收
      props: ['content', 'a', 'b'],
      template: `
          <span>{{ content }}-{{ a }}-{{ b }}</span>
          `
    });

    app.mount("#app");
  </script>
</body>

image-20210707130129459



②xx-xx=’'传递,props中xxXx接收

静态传递带有-号的属性:content-aa='xxx内容',需要使用props: ['contentAa']接收。

  • content-aa => contentAa,去掉-,并且之后字母大写拼接来接收!

示例

<body>

  <div id="app">
  </div>

  <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
  <script>
    const app = Vue.createApp({
      //1、传递带有-的参数:content-aa
      template: `
          <exerTab content-aa='xxx内容' />
          `
    });

    app.component('exerTab', {
      //2、对应该类参数props接收,需要去掉-以及其后大写:contentAa
      props: ['contentAa'],
      template: `
          <span>{{ contentAa }}</span>
          `
    });

    app.mount("#app");
  </script>
</body>


4.2、认识单项数据流

单项数据流:子组件可以使用父组件传递过来的数据,但是决定不能修改传递过来的数据!(可以想成调用函数时传递过来的是基本类型,而非地址引用传递)

效果:若是在子组件中修改父组件传递过来的值时就会报出warning提示并且会阻止修改该值!

<body>
  <div id="app"></div>

  <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          content: '父组件中的content'
        }
      },
      template: `
          <exerTab :content='content' />
          `
    });

    app.component('exerTab', {
      props: ['content'],
      methods: {
        modifyContent() {
          this.content = '子组件修改了content';
        }
      },
      //绑定单击事件来尝试修改
      template: `
          <span @click="modifyContent()">{{ content }}</span>
          `
    });

    app.mount("#app");
  </script>
</body>

image-20210708094948669



4.3、解决方案:实现在子组件中修改父组件传递过来的参数

方案:通过在data对象中设置一个新属性来接收传递来的参数,之后对该新属性进行赋值修改也能够达成目的!

示例

<body>
    <div id="app"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                count: 0
            }
        },
        template: `
            <div>
                <changlu :count="count"/>
            </div>
        `
    });

    app.component('changlu', {
        props: ['count'],
        data() {
            return {
                //1、创建一个属性来进行代替count
                mycount: this.count
            }
        },
        methods: {
            //2、对新创建的属性进行赋值操作
            handlerClick() {
                this.mycount++;
            }
        },
        template: `
            <span @click="handlerClick()">{{mycount}}</span>
        `

    });

    app.mount("#app");
</script>

GIF



4.4、设计单向数据流原因

image-20210708221753439

核心:通过父组件传递到子组件中的data对象里的值不能够随意更改否则就会影响到其他复用的组件了!!!



五、No-Props属性

5.1、不使用props传递时效果(默认会继承到子组件中,仅仅是单标签情况)

简而言之:就是不使用props属性来接收的属性!

<body>
    <div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
    const app = Vue.createApp({
        data() {
            return {
                count: 0
            }
        },
        template: `
            <div>
                <changlu msg="hello,cl!"/>
            </div>
        `
    });

    app.component('changlu', {
        //若是不使用props接收默认就会放置在template的标签中
        template: `
            <span>changlu组件</span>
        `

    });

    app.mount("#app");
</script>

image-20210708222224514

效果:可以看到对应的键值对继承到了子组件标签中。若是不想让键值对继承到子组件上,可以在组件对象中添加如下属性:

inheritAttrs: false

image-20210708222424974



5.2、认识$attrs

若是不使用props属性接收且template模板有多个标签:不会生效

image-20210708222919410

若此时有个需求就是让某个标签具有对应的属性:此时就使用到了$attrs对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5AmAOaDB-1652144855684)(C:\Users\93997\AppData\Roaming\Typora\typora-user-images\image-20210708223102983.png)]


实际应用$attrs

this.$attrs:一个代理对象,其中包含了所有父组件传递子组件时的键值对中,可以从这里获取!

示例:

<body>
    <div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
    const app = Vue.createApp({
        data() {
            return {
                count: 0
            }
        },
        template: `
            <div>
                <changlu msg="hello,cl!" msg1="changlugege"/>
            </div>
        `
    });

    app.component('changlu', {
        methods: {
            //this.$attrs:是一个代理对象,该对象中包含父组件传值过来的所有属性
            handleClick() {
                console.log(this.$attrs);
            }
        },
        //v-bind:msg="$attrs.msg1" =>  绑定单个值
        //v-bind="$attrs" => 绑定所有父组件传递过来的值
        template: `
            <span @click="handleClick()">changlu组件</span>
            <span v-bind:msg="$attrs.msg1">changlu组件</span>
            <span v-bind="$attrs">changlu组件</span>
        `
    });

    app.mount("#app");
</script>

image-20210708223640889

image-20210708223740028

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。