9.组件

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件</title>
</head>
<body>
<!--
1.组件也分为全局组件和局部组件:
 1.1.全局组件是使用Vue.component()方法来注册,该方法接受两个参数,第一个参数是组件的ID(名字),第二个参数
 是一个函数对象(使用Vue.extend()方法创建的组件构造器),也可以是一个选项对象。语法如下:
    Vue.component(id,[definition])
 1.2.局部组件:是在Vue实例的选项对象中使用components选项来注册
2.注册组件是,data选项是一个函数(也必须是一个函数)。这是因为组件是可复用的Vue实例,
如果还是允许使用先前根实例的数据定义方式,那么所有复用的组件实例都将共享同一份数据,显然,这很容易导致混乱。采用
函数定义方式,那么每个组件实例都将拥有自己的一份返回对象的独立拷贝,每复用一次组件,data函数就执行一次,
从而返回一个新的数据对象。
3.组件的内容通过template选项来定义,当使用组件时,组件所在的位置将被template选项的内容所替换。
此外,组件的内容必须用一个根元素来包裹,且只能有一个根元素
4.因为HTML并不区分元素和属性的大小写,所以浏览器会把所有大写字符解释为小写字符,如下的ButtonCounter,这就会
导致找不到组件而爆错了,解决办法是在DOM模板中采用kebab-case命名来引用组件。
5.由于HTML并不支持自闭合的自定义元素,所以在DOM模板中就不用把ButtonCounter的组件当做自闭合元素来使用
6.调用Vue.component()方法注册全局组件时,第二个参数除了传入选项对象外,还可以传入Vue.extend()方法创建的组件构造器。
Vue.extend()方法使用基础Vue构造器创建一个"子类",该方法只有一个参数,接收一个包含组件选项的对象。

-->
<div id="app">
    <button-counter></button-counter>
</div>
<script>
    Vue.component('ButtonCounter',{
        data: function () {
            return {
                count:0
            }
        },
        template: '<button v-on:click="count++">You clicked me {{count}} times.</button>'
    })

    var vm = new Vue({
        el: '#app',
        data: {
            count:0
        }
    });
</script>
</body>
</html>

通过extend:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件(extend)</title>
</head>
<body>
<!--
1..调用Vue.component()方法注册全局组件时,第二个参数除了传入选项对象外,还可以传入Vue.extend()方法创建的组件构造器。
Vue.extend()方法使用基础Vue构造器创建一个"子类",该方法只有一个参数,接收一个包含组件选项的对象。

-->
<div id="app">
    <button-counter></button-counter>
</div>
<script>
  let MyComponent =  Vue.extend({
        template: '<button @click="count++">You clicked me {{count}} times</button>',
        data: function () {
            return {
                count: 0
            }
        }
    })
    Vue.component('ButtonCounter',MyComponent)

    var vm = new Vue({
        el: '#app'
    });
</script>
</body>
</html>

局部组件的形式:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件(局部)</title>
</head>
<body>
<!--
1.对于components选项对象来说,它的每个属性的名字就是自定义元素的名字,其属性值就是这个组件的选项对象。
2.局部注册组件也可以使用Vue.extend()方法创建的组件也是可以使用Vue.extend()方法创建的组件构造器。
3.全局注册的组件可以在任何Vue实例中使用,而局部注册的组件只能在父组件的模板中使用。
-->
<div id="app">
    <button-counter></button-counter>
</div>
<script>

    var vm = new Vue({
        el: '#app',
        components:{
            ButtonCounter:{
            data:function () {
             return{
                 count:0
             }
            },
            template: '<button @click="count++">You clicked me {{count}} times</button>'
        }
        }
    });
</script>
</body>
</html>

父传子(prop):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件-父传子(prop)</title>
</head>
<body>
<!--
1.组件是当做自定义元素来使用的,而元素一般是有属性的,同样,组件也可以有属性。在使用组件时,给组件元素设置属性,组件内部接受是通过组件内部是注册一些自定义的属性,
称为prop,这些prop是放在组件的props选项中定义的;之后在使用组件时,就可以把这些prop的名字作为元素的属性名来使用,通过属性向组件传递数据,这些数据
将作为组件实例的属性被使用。
2.在props选项中定义的prop,可以当成该组件实例的数据属性来使用。
3.props选项中声明的每一个prop,在使用组件时,作为元素的自定义属性来使用,属性值会被传递给组件内部的prop。
4.因为HTML中的属性名是不区分大小写的,所以要采用驼峰命名法,采用驼峰命名法的prop名要使用等价的(短横线分隔命名)名字来使用,如果在字符串模板中或单文件组件内使用
则没有这个限制,在字符串模板中,除了各种命名可以直接使用之外,组件还可以当做自闭合元素来使用。
-->
<div id="app">
    <post-item post-title="Vue.js无难事"></post-item>
    <post-list></post-list>
</div>
<script>
    Vue.component('PostItem',{
       props:['postTitle'],
        //postTitle就像data中定义的数据属性
        //在该组件中可以如"this.postTitle"这样使用
        template: '<h3>{{postTitle}}</h3>'
    })
    //字符串模板(4)
    Vue.component('PostList',{
        //在字符串模板中可以使用PascalCase命名组的组件名
        //和camelCase命名的prop名
        template: '<div> <PostItem post-title="Vue.js无难事"></PostItem></div>'
    })

    var vm = new Vue({
        el: '#app',
        data: {
            count:0
        }
    });
</script>
</body>
</html>

 

多个prop传值:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件-父传子(多个prop传递)</title>
</head>
<body>
<!--
1.在组件中和普通的HTML元素传值一样,要接受动态值,必须要使用 v-bind指令,否则,接收的值都是静态的字符串值。
-->
<div id="app">
    <post-list></post-list>
</div>
<script>
    Vue.component('PostItem',{
       props:['author','title','content'],
        template: `
        <div>
         <h3>{{title}}</h3>
         <p>作者:{{author}}</p>
         <p>{{content}}</p>
        </div>
        `
    })
    Vue.component('PostList',{
        data(){
            return{
                author:'孙鑫',
                title:'Vue.js无难事',
                content:'这本书不错'
            }
        },
        template: `
        <div>
        <PostItem
         :author="author"
         :title="title"
         :content="content"
        >
       </PostItem>
        </div>
`
    })
    var vm = new Vue({
        el: '#app',
        data: {
            count:0
        }
    });
</script>
</body>
</html>

对象形式传值(1):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件-父传子(prop对象形式)</title>
</head>
<body>
<!--
1.如果子组件定义的prop较多,调用时就需要写较多的属性,然后一一赋值,这很麻烦,为此我们可以使用不带参数的v-bind来传入一个对象,你只需要将该对象的属性和
组件的prop一一对应即可。
2.我们在data中定义了一个post对象,它的属性值和PostItem的prop一一对应,在<PostItem>元素上使用了不带参数的v-bind指令,传入post对象,该对象的所有属性将
作为prop传入。虽然直接传入一个对象,将其所有属性值作为prop传入可以简化代码的编写,但也容易造成一些混乱,而在实际业务中开发时,子组件通常是以对象来接收数据,
父组件以对象的方式来传值
-->
<div id="app">
    <post-list></post-list>
</div>
<script>
    Vue.component('PostItem',{
       props:['author','title','content'],
        template: `
        <div>
         <h3>{{title}}</h3>
         <p>作者:{{author}}</p>
         <p>{{content}}</p>
        </div>
        `
    })
    Vue.component('PostList',{
        data(){
            return{
               post:{
                   author:'孙鑫',
                   title:'Vue.js无难事',
                   content:'这本书不错'
               }
            }
        },
        template: `
        <div>
        <PostItem
        v-bind="post"
        >
       </PostItem>
        </div>
`
    })

    var vm = new Vue({
        el: '#app'
    });
</script>
</body>
</html>

对象形式(最常用写法):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件-父传子(prop对象形式)</title>
</head>
<body>
<!--
1.如果子组件定义的prop较多,调用时就需要写较多的属性,然后一一赋值,这很麻烦,为此我们可以使用不带参数的v-bind来传入一个对象,你只需要将该对象的属性和
组件的prop一一对应即可。
2.我们在data中定义了一个post对象,它的属性值和PostItem的prop一一对应,在<PostItem>元素上使用了不带参数的v-bind指令,传入post对象,该对象的所有属性将
作为prop传入。虽然直接传入一个对象,将其所有属性值作为prop传入可以简化代码的编写,但也容易造成一些混乱,而在实际业务中开发时,子组件通常是以对象来接收数据,
父组件以对象的方式来传值
-->
<div id="app">
    <post-list></post-list>
</div>
<script>
    Vue.component('PostItem',{
       props:['post'],
        template: `
        <div>
         <h3>{{post.title}}</h3>
         <p>作者:{{post.author}}</p>
         <p>{{post.content}}</p>
        </div>
        `
    })


    Vue.component('PostList',{
        data(){
            return{
               post:{
                   author:'孙鑫',
                   title:'Vue.js无难事',
                   content:'这本书不错'
               }
            }
        },
        template: `
        <div>
        <PostItem
        :post="post"
        >
       </PostItem>
        </div>
`
    })
    var vm = new Vue({
        el: '#app'
    });
</script>
</body>
</html>

单向数据流:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件-单向数据流</title>
</head>
<body>
<!--
1.通过prop传递的数据是单向的,父组件的属性变化会向下传递给子组件,但是反过来不行。这可以防止子组件意外改变父组件的状态,从而导致应用程序的数据流难以理解。
2.每次父组件更新时,子组件中所有的prop都会刷新为最新的值。这意味着我们不应该在一个子组件内部去改变prop,如果这样做了,vue会站在浏览器的控制台中给出警告。
3.在两种情况下可能需要改变组件的prop。一种是定义一个prop,以方便父组件传递初始值,在子组件内将这个prop作为一个本地的prop数据来使用,遇到这种情况,解决
办法是定义一个本地的data属性,然后将prop的值作为其初始值,后续操作只访问这个data属性。第二种情况是prop接受数据后需要转换后使用,这种情况是可以使用计算
属性来解决的。(具体原因是,如果无论子组件怎么变,当父组件变换时,子组件的值会被父组件变换掉)
https://blog.csdn.net/weixin_44584442/article/details/111938708
-->
<div id="app">
    father:
    <button @click="count++">{{ count }}</button>
    <son-cmp :count='count'></son-cmp>

</div>
<script>
    Vue.component('son-cmp', {
        props: ['count'],
        template: `
        <div>
            son:
            <button @click="count++">{{ count }}</button>
        </div>
    `
    })
    const vm = new Vue({
        el: '#app',
        data: {
            count: 0
        }
    })
</script>
</body>
</html>

prop的验证:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件-prop验证</title>
</head>
<body>
<!--
1.当开发一个通用组件时,我们希望父组件通过prop传递的数据类型是符合要求的。为此Vue.js还提供了prop验证机制,在定义props选项时,使用一个带验证需求的对象
来代替之前一直使用的字符串数组
2.prop验证发生在组件实例创建之前,因此实例的属性(如data、计算属性等)在default或validator函数中不可用
3.验证的type可以是下列原生构造函数中的一个:
 3.1.String
 3.2.Number
 3.3.Boolean
 3.4.Array
 3.5.Object
 3.6.Date
 3.7.Function
 3.8.Symbol
 3.9.自定义构造器
-->
<div id="app">
    <my-component :username="test"></my-component>
</div>
<script>
    function Person(firstName,lastName){
        this.firstName = firstName
        this.lastName = lastName
    }
    Vue.component('my-component',{
        data:function () {
          return{
              count :0
          }
        },
      props:{
          //基本类型检查('null'和'undefined'会通过任何类型验证)
          age:Number,
          //多个可能的类型
          tel:[String,Number],
          //必填的字符串
          username:{
              type: String,
              required:true
          },
          //带有默认值的数字
          sizeOfPage:{
              type: Number,
              default: 10
          },
          //带有默认值的对象
          greeting:{
              type:Object,
              default: function () {
                 return {
                     message: 'hello'
                 }
              }
          },
          //自定义验证函数
          info:{
              validator:function (value) {
                  return ['success','waring','danger'].indexOf(value) !==-1
              }
          },
          //验证author的值是否是通过 new Person创建的
          author: Person
      },
        template: '<button v-on:click="count++">You clicked me {{count}} times.</button>'
    })
    var vm = new Vue({
        el: '#app',
        data: {
            count:0,
            test:"测试"
        }
    });
</script>
</body>
</html>

非prop属性:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="../JS/vue.js"></script>
    <title>组件-非prop属性</title>
    <style>
        .child{
            background-color: red;
        }
        .parent{
            opacity: 0.5;
        }
    </style>
</head>
<body>
<!--
1.在使用组件时,组件的使用者可能会向组件传入未定义的prop的属性。在Vue.js中,这也是许可的,组件可以接受任意的属性,而这些外部设置的属性会被添加到这个组件的
根元素上。
2.MyInput组件没有定义任何的prop,根元素是<input>,在DOM模板中使用<my-input>元素时设置了type属性,这个属性将被添加到MyInput组件的根元素<input>上,
渲染结果为<input type="text">。此外,在MyInput组件的模板中还使用了class属性,同时在DOM模板中也设置了class属性,在这种情况下,两个class属性的值会被
合并,最终渲染为<input type="text" class="child parent">。要注意的是,只有class和style属性的值会合并,对其他属性而言,从外部提供给组件的值会替换
掉组件内部设置好的值。假设MyInput组件的模板是<input type="text">,如果父组件传入 type="checkbox",就会替换掉 type="text",最后渲染结果就变成了
<input type="checkbox">
3.如果不希望组件的根元素基础外部设置的属性,可以在组件的选项中设置 inheritAttrs:true,

-->
<div id="app">
    <my-input type="text" class="parent" ></my-input>
</div>
<script>

    Vue.component('MyInput',{
        // inheritAttrs:true,
        template: '<input type="text" class="child">'
    })

    var vm = new Vue({
        el: '#app'
    });
</script>
</body>
</html>

不想更了 太多了 就一个组件还有十几个 其余加起来最起码还有几百个,有需要的私聊我吧。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值