Vue-组件

Vue组件

组件注册

全局组件

<body>
    <div id="app">
        <b>这是一个html中的b标签</b>
        <!-- 这里面将存放一个全局组件 -->
      	<hr>
        <aa></aa>
        <hr>
        <aa-1></aa-1>
        <!--PascalCase写法使用时必须使用kebab-case来获取 这里获取不到-->
        <hr>
        <AaAa2></AaAa2>
        <hr>
        <!--正确的引用方式-->
        <aa-aa2></aa-aa2>
    </div>
</body>
全局组件注册:

Vue.component(‘需要注册的组件名’,{

“选项对象”

});

注意事项:

  • 注册全局组件时 V需要同Vue实例一样 必须大写 且要放在Vue实例之前
  • 全局组件只能在Vue根实例绑定的标签内中使用
<script src="/lib/vue-2.6.12.js"></script>
<script>
    // Vue.component('组件名',{"选项对象"})
    Vue.component('aa', {
        template: `<b>这是一个全局组件的b标签</b>`
    })
    // kebab-case写法
    Vue.component('aa-1', {
        template: `<b>这是kebab-case全局组件的定义放式</b>`
    })
    // PascalCase写法
    Vue.component('AaAa2', {
        template: `<b>这是PascalCase全局组件的定义放式</b>`
    })
    new Vue({
        el: '#app',

    });
</script>
全局组件命名规则及获取方式
命名规则
	 // kebab-case写法
    Vue.component('aa-1', {
        template: `<b>这是kebab-case全局组件的定义放式</b>`
    })
    // PascalCase写法
    Vue.component('AaAa2', {
        template: `<b>这是PascalCase全局组件的定义放式</b>`
    })
获取方式

注意:

无论哪种命名方式 在body中获取时都只能采用kebab-case方式进行获取 因为html不区分大小写PascalCase方式获取不到

 		<!--PascalCase写法使用时必须使用kebab-case来获取 这里获取不到-->
        <hr>
        <AaAa2></AaAa2>
        <hr>
        <!--正确的引用方式-->
        <aa-aa2></aa-aa2>

在这里插入图片描述

组件内容描述

组件选项
template选项

用来设置组件结构最终可以被引入根实例或者其他组件中

 // template选项用来设置组件结构 最终可以被引入根实例或者其他组件之中
    Vue.component('aa1', {
        template: `<b>这是第b一个组件</b>`
    });

template选项注意事项

template中不能有平级的根实例 如果有多个平级的div 只会显示第一个div

 Vue.component('aa2', {
        template: `
                <div>
                    <b>这是组件内div中的第一个b的标签</b>
                    <b>这是组件内div中的第二个b的标签</b>
                </div>
         `
    });
    Vue.component('aa3', {
        template: `
                <div>
                <b>这是第一个div中的b</b>
                </div>
                <div>
                <b>这是第二个div中的b</b>
                </div>
      `
    });

在这里插入图片描述##### data选项

用来存储组件中的数据

与根实例data不同的是 组件中的data选项必须设置为函数 数据设置在返回值对象中

为什么组件data选项使用函数写法?

**使用函数的目的是因为data中定义的每个变量都是独立的存在 **

用来保证每个实例都有独立选项 其中一个发生改变 其他不受影响

	<aa4></aa4>
    <hr>
    <b1></b1>
    <hr>
    <b1></b1>
    <hr>
    <b1></b1>
        
    Vue.component('b1', {
        template: '<b>{{age}}</b>',
        data: function () {
            return {
                age: Math.floor(Math.random() * 100 + 1) // 年龄随机,每个实例的年龄都不相同
            }
        }
    })
    Vue.component('aa4', {
        template: `
        <b>{{name}}</b>
        `,
        data: function () {
            return {
                name: 'aa'
            }
        }
    })
       

如下图所示 三个随机数数据由data产生 每个实例都是独立的互不影响
在这里插入图片描述

局部组件

局部组件定义方式
直接书写组件选项
 new Vue({
    el: '#app',
	....
    components: {
        '组件名': {/*组件选项*/},
        '组件名': {/*组件选项*/},
		....
    }
单独配置组件选项
 // 单独配置组件的选项对象
let aa = {/*组件选项*/};
new Vue({
    el: '#app',
    components: {
        '组件名': aa
    }
});

全局组件与局部组件区别

  • 全局注册的组件能够被所有的根实例所使用
  • 局部注册的组件只能够在当前根实例中使用
 <div id="app">
        <aa-bb></aa-bb>
        <aa-cc></aa-cc>
        </div>
        <hr/>
        <div id="app2">
        <aa-cc></aa-cc>
        <!-- 这里看不到效果,因为局部组件注册到了app中 -->
        <aa-bb></aa-bb>
        <!-- 全局组件在这里可以使用 因为全局组件能够被所有实例使用 -->
    </div>
    <script src="../js/vue.min.js"></script>
   <script>
    Vue.component('aa-bb',{
       template: '<b>全局组件</b>'
    });
    new Vue({
        el: '#app',
        components: {
            'aa-cc': {
                template: '<b>局部组件</b>'
            }
        }
    });
    new Vue({
        el: '#app2'
    });
</script>

组件通信

父组件向子组件传值

通过子组件的props选项接收父组件的值

注意事项:
  • 子组件的props选项中不要存在与子组件中的data中同名选项
  • props是一个数组形式 其中的值(prop)可以看成是组件(自定义标签的属性)
  • 父子组件中的prop所有prop都是单向绑定的 只能由父组件向子组件传值
  • 动态绑定以:prop 或者v-bind:prop命名 (prop是在props中定义的值)在此处相当于 id name 等
<body>
    <!-- 父组件 -->
    <div id="app">
        <!-- 三个子组件 -->
        <!-- 静态内容写法 -->
        <aa id="2" name="张三" did="20" dname="销售部"></aa>
        <hr>
        <!-- 动态绑定写法 传递静态内容 -->
        <aa v-bind:id="3" name="李四" did-="30" dname="财务部"></aa>
        <hr>
        <!-- 动态绑定写法 父组件给子组件传值 -->
        <aa :id="id" :name="name" :did="dept.id" :dname="dept.dname"></aa>
    </div>
</body>
<script src="/lib/vue-2.6.12.js"></script>
<script>
    Vue.component('aa', {
        props:['id','name','did','dname'],
        template: `
        <div>
              <b>编号:{{ id }}</b><br/>
              <b>姓名:{{ name }}</b><br/>
              <b>部门编号:{{ did }}</b><br/>
              <b>部门名称:{{ dname }}</b>
          </div>
        `
    });
    new Vue({
        el: '#app',
        data: {
            id: 1,
            name: '王五',
            dept: {
                id: 10,
                dname: '研发部'
            }
        }
    });
</script>

在这里插入图片描述

props命名规则
  • 建议prop的命名使用 camelCase 方式 父组件绑定时使用 kebab-case 方式
  • 因为在props中定义是属于javaScript 中的 区分大小写
  • 页面中是属于 html 范畴的 不区分大小写

子组件向父组件传值

子组件通过自定义事件的方式向父组件传值

<body>
    <div id="app">
        <b>{{number1}}</b>
        <aa @ff="addNumber1()"></aa>
    </div>
</body>
<script src="/lib/vue-2.6.12.js"></script>
<!-- 子组件通过自定义事件向子组件传值 -->
<!-- 
    子组件通过事件向父组件传值
    1、当点击子组件的+1按钮时,触发了函数 addNumber2
    2、在函数 addNumber2 中执行了子组件变量 number2 自增和触发了自定义事件 ff
    3@ff 事件触发后执行了函数 addNumber1 自增了 number1的值
 -->
<script>
    // 第一个组件,当这个组件文本框的值发生改变时 ,将文本框的值传递给父组件
    Vue.component('aa', {
        data() {
            return {
                number2: 1
            }
        },
        template: `
    <div>
          <b>{{ number2 }}</b>
          <button @click="addNumber2">+1</button>
    </div>
    `,
        methods: {
            addNumber2() {
                // 触发自定义事件 ff
                 this.$emit('ff');
                this.number2++;
            }
        }
    });
    new Vue({
        el: '#app',
        data() {
            return {
                number1: 1
            }
        },
        methods: {
            addNumber1() {
                this.number1++;
            }
        }
    });
</script>

注:

  • 实现方式其实就是在页面加载后显示子组件内容
  • 点击子组件按钮 调用子组件addNumber2事件 在子组件addNumber2触发自定义事件ff让子组件中数据++
  • 触发事件后 父组件数据调用 自身事件 实现逻辑
子组件向父组件传值的具体实现

在上面的案例中、是通过调用事件实现逻辑的 下面将演示如何触发事件的同时实现参数传递

 <div id="app">
    传递过来的值:{{ num3}}
 </div>
  //传值
    Vue.component('a-a3', {
        template: `
      <div>
        <input  @input="addNumber2">
     </div>
        `,
        methods: {
            // 第一个值为当前文本框值 和一个常量字符串
            addNumber2(e) {
                console.log(e)
                this.$emit('ff2', e.target.value, 'aa');
            }
        }
    });
    new Vue({
        el: '#app',
        data() {
            return {
                num3: ''
            }
        },
        methods: {
            pastNum(a, b) {
                console.log(a)
                this.num3 = a + ',' + b;

            },
        }
    });
具体实现方式:
  • 在页面加载后显示了子组件内容 当文本框中输入内容后 调用子组件事件 addNumber2
  • 子组件事件内调用自定义事件ff2 并传递两个值 第一个值为当前文本框值 第二个值为一个常量字符串
  • 在父组件内 接收两个值 并赋给num3 实现数值传递

事件调用注意事项:

Vue中事件绑定加括号和不加括号区别

  • @click="fun" 不带括号 不写实参时 默认方式 默认会传递 event(事件对象)
  • @click="fun(value)" 只要带括号 无论是否传值 都属于传递实参给函数 event(事件对象接收不到)
  • 如果需要实参 又需要event(事件对象)、就需要手动传入event(事件对象) @click=“fun($event, value)”

兄弟组件传值

实现方式其实就是利用之前的两个知识 先使用子组件给父组件传值 然后父组件给子组件传值

<div id="app">
        组件1
        <a-a1 @ff="change01"></a-a1>
        <br>
        父组件:{{value}}<br />
        第二个组件
        <a-a2 :value02="value"></a-a2>
</div>
<script src="/lib/vue-2.6.12.js"></script>
<script>
    //第一个组件 当这个组件的文本框的值发生改变时   将文本框的值传给父组件
    Vue.component('a-a1', {
        data() {
            return {
                value01: 'a'
            }
        },
        template: `
        <div>
          <input v-model="value01"/>
          <button @click="changeComponent">点击我</button>
        </div>
        `
        ,
        methods: {
            changeComponent() {
                // 触发了ff事件 并将value的值传递出去了
                this.$emit('ff', this.value01)
            }
        }
    });
    //第二个组件 负责接收父组件传递过来的值
    Vue.component('a-a2', {
        props: ['value02'],
        template: `
    <div>
    {{value02}}
    </div>
    `
    });
    new Vue({
        el: '#app',
        data: {
            value: '原始的值'
        },
        methods: {
            change01(a) {
                // 将传递过来的参数赋予变量value
                this.value = a;
            }
        }
    });
</script>

EventBus传值

说明:

  • 在之前的传值方式中 如果组件关系比较复杂 根据之前的知识 值传递起来也会比较复杂
  • 组件数据中转过程中 data 中会存在 许多与当前组件功能无关的数据
  • EventBus(事件总中心) 是一个独立的事件中心 可以管理不同组件传值问题
优点:
  • 组件和组件之间不需要设置多余的 data 数据。

  • 组件和组件不需要找到之间的关系,只需要 EventBus 中心中进行处理就行。

  • EventBus仅仅存储的用来进行传值操作的事件功能 而不会进行存储操作 只是一个中转站 -

  • Vue通过创建一个新的Vue实例来管理组件传值操作,组件通过给实例注册事件、调用事件来实现数据传递

// EventBus 通过一个新的 Vue 实例来管理,新的 Vue 实例不需要设置事件选项。空的 Vue 实例。
   let bus = new Vue();
实现步骤:
  • 发送数据的组件触发 bus 事件,接收的组件给 bus 注册对应事件。
  • 接收事件的组件给 bus 注册对应事件通过 $on() 操作。
注意事项:
  //传值的组件中
    函数(){
    bus.$emit('事件名',参数列表);
    }
    // 接收的组件中 一般写入到组件选项的 created 中
    created(){
    bus.$on('事件名',(参数列表)=>{函数体});
    }

具体实现:

<body>
    <div id="app">
        <a-a1></a-a1>
        <hr>
        <a-a2></a-a2>
    </div>
</body>
<script src="/lib/vue-2.6.12.js"></script>
<script>
    let bus = new Vue();
    Vue.component('a-a1', {
        data() {
            return {
                count: 1
            }
        },
        template: `
        <div>
          <p>{{ count }}</p>
          <button @click="changeCount">+1</button>
          </div>
`,
        methods: {
            changeCount() {
                this.count++;
                bus.$emit('ff', this.count)
            }
        }
    });
    Vue.component('a-a2',{
        data(){
            return{
                count:1
            }
        },
        template:`
        <b>{{count}}</b>
        `,
        created(){
            bus.$on('ff',(yourCount)=>{
                this.count=yourCount
            })
        }
    });
    new Vue({
        el: '#app'
    });
</script>

组件插槽

快捷的设置组件内容

单个插槽

说明:

  • 组件标签可以像 HTML 标签一样设置内容,那么组件的使用灵活度会很高。
  • 但是问题在于 如果在html中书写组件内容 自定义组件内容会被抛弃
  • 如果需要组件内部生效 就需要使用组件插槽实现可以通过 进行插槽设置。
  • 代表的是组件的内容区域, 标签内部书写的内容会自动替换 位置的内容,
  • 这样在多次使用 自定义标签时,可以传递不同的内容来达到快速传值的目的。
  • 有点像我们在 Java 中学习的占位符效果, 就是占位符,自定义中的内容就是要传递的值。
<body>
    <div id="app">
        <!-- 组件插槽可以快捷的设置组件内容。 -->
        <!--组件-->
        <a-a1>我是一个内容</a-a1>
        <hr>
        <a-a1>
            另一段内容<br />
            <span>组件的主体内容</span>
        </a-a1>
        <hr>
        <a-a1>
            <!--只能获取到父组件的 data 数据-->
            {{content}}
        </a-a1>
    </div>
</body>
<script src="/lib/vue-2.6.12.js"></script>
<script>
    Vue.component('a-a1', {
        template: `
        <div>
        <b>我是组件的内容</b>
        <slot>我是插槽的默认值</slot>
        </div>
        `
    });
    new Vue({
        el: '#app',
        data() {
            return {
                content: 1
            }
        },

    });
</script>
具名插槽

如果组件中由多个位置需要设置插槽 需要给设置name 这种具有名称的插槽,称为具名插槽

<body>
    <div id="app">
        <a-a1>
            <!--template标记没有其他作用 就是标识当前内容是赋予那个slot。v-slot:名字-->
            <template v-slot:top>
                {{title}}
            </template>
            <template v-slot:default>
                {{content}}
            </template>
            <template v-slot:bottom>
                {{bottom}}
            </template>
            <hr>
            <!-- 具名插槽缩写形式 -->
            <!-- <template #top>
        {{title}}
    </template> 
    {{content}}
     <template #bottom>
        {{bottom}}
    </template> -->
        </a-a1>
</body>
<script src="/lib/vue-2.6.12.js"></script>
<script>
    Vue.component('a-a1', {
        template: `
         <div>
              <h1>我是头部部分</h1>
              <slot name="top"></slot>
              <h1>我是中间部分</h1>
              <slot>我的默认名字是default</slot>
              <h1>我是底部部分</h1>
              <slot name="bottom"></slot>
         </div>
     `});
    new Vue({
        el: '#app',
    });
</script>
作用域插槽

特点:

  • 解决之前插槽中只能使用父组件data数据
  • 能够在插槽中使用子组件data数据
  • 组件将需要被插槽使用的数据通过 v-bind:要传递的变量名=“要传递的变量名” 绑定给
  • 这种用于给插槽传递数据的属性称为插槽 prop
<body>
<div id="app">
    <guanwei>
        <!--gwObj是子组件的实例 可以通过子组件的实例获取数据-->
        <template v-slot:default="gwObj12">
            父组件内容:{{content}}<br/>
            子组件内容:{{gwObj12.content}}
        </template>
    </guanwei>
</div>
</body>
<script src="/lib/vue-2.6.12.js"></script>
<script>
    Vue.component('guanwei', {
        template: `
          <div>
          <h3>v-bind:变量名绑定要使用的数据 前后 content 建议一致</h3>
          <h4>第一个 content 是我们起的名称供 template 调用,第二个是 变量名</h4>
          <slot v-bind:content="content"></slot>
          </div>
        `,
        data() {
            return {
                title: '子组件的标题',
                content: '子组件的内容'
            }
        }
    });
    new Vue({
        el: '#app',
        data: {
            title: '父组件的标题',
            content: '父组件的内容'
        }
    });
</script>

内置组件

动态组件

特点:

  • 动态适用于多个组件的频繁切换处理
  • 用于将一个"元组件" 渲染为动态组件 以is属性值决定渲染哪个组件 类似于v-if v-show的效果
<body>
    <div id="app">
        <!--注意这里组件名如果是常量字符串 必须加入''-->
        <!-- 实现多个组件快速切换 -->
        <component :is="name">{{name}}</component>
        <br>
        <button @click="changeName('a-a1')">a-a1</button>
        <button @click="changeName('a-a2')">a-a2</button>
        <button @click="changeName('a-a3')">a-a3</button>
    </div>
</body>
<script src="/lib/vue-2.6.12.js"></script>
<script>
    Vue.component('a-a1', { template: '<div><b>这是第一个组件</b><slot></slot></div>' })
    Vue.component('a-a2', { template: '<div><b>这是第二个组件</b><slot></slot></div>' })
    Vue.component('a-a3', { template: '<div><b>这是第三个组件</b><slot></slot></div>' })

    // Vue根实例
    new Vue({
        el: '#app',
        data: {
            name: 'ff01'
        },
        methods: {
            changeName(n) {
                this.name = n;
            }
        }
    });
</script>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值