Vue学习2:组件化开发(基本知识、父子间通信、slot、模块化开发)

Vue学习2:组件化开发(基本知识、父子间通信、slot、模块化开发)

一、基本知识

组件化:
组件化是Vue.js中的重要思想,它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。任何的应用都会被抽象成一颗组件树

1. 组件的使用

1.创建组件构造器:Vue.extend()

        //1.创建组件构造器对象
        const cpnC = Vue.extend({
            template: `
            	<div>
                	<h2>标题</h2>
                	<p>内容</p>
            	</div>`
        });

2.注册组件:Vue.component('my-cpn', cpnC);
创建构造器+注册语法糖(更常用):就是把template的内容直接写到cpnC中,省去extend这一步
全局组件:

Vue.component('myCpn', {
	template: `
		<div>
			<h2>标题</h2>
			<p>内容</p>
		</div>`
})

局部组件:

const app = new Vue({
	el: '#app',
	data: {},
	components: {
		myCpn: {
			template: `
				<div>
					<h2>标题</h2>
					<p>内容</p>
				</div>`
		}
	}
})

3.使用组件:在Vue实例的作用范围内(id="app"内)使用 <my-cpn></my-cpn>

2. 全局组件和局部组件

全局组件:可以在多个Vue实例下使用
在Vue外部注册的:Vue.component('myCpn', cpnC);

局部组件:只能在特定的Vue实例下使用(用得更多)
在Vue中写在components中:components: { myCpn: cpnC }

3. 父组件和子组件

app是cpnC2的父级(可看作root),cpnC2是cpnC1的父级,只有注册了,才可以在其实例范围下使用

    <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
            }
        });
        const app = new Vue({
            el: '#app',
            data: {
            },
            components: {
                cpn2: cpnC2
            }
        })
    </script>

4. 模板的分离写法

在这里插入图片描述

5. 组件数据

组件中的html结构要使用数据,使用组件中的data来设置,data是一个函数,返回一个对象
为什么是一个函数?因为当多次使用组件时,data是函数的形式,则会重新调用函数,里面的数据对于每个组件来说是私有的,不是公用的

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

    <!-- html结构分离 -->
    <template id="cpn1">
        <h2>{{title1}}</h2>
    </template>
    <template id="cpn2">
        <h2>{{title2}}</h2>
    </template>

    <script src="../vue.js"></script>
    <script>
        //全局组件
        Vue.component('cpn1', {
            template: '#cpn1',
            data() { //注意data是一个函数 返回一个对象
                return {
                    title1: '全局组件'
                }
            }
        })
        const app = new Vue({
            el: '#app',
            data: {

            },
            components: {
                cpn2: {
                    template: '#cpn2',
                    data() { //data是函数 返回一个对象
                        return {
                            title2: '局部组件'
                        }
                    }
                }
            }
        })
    </script>
</body>

二、父子组件通信

在开发中,往往需要上层组件请求网络数据,再传递给下面的组件进行展示
父子组件间通信:
1.通过props向子组件传递数据
2.通过事件向父组件发送消息
在这里插入图片描述

1. 父传子

props

<body>
    <div id="app">
        <!-- 要用v-bind语法绑定数据 -->
        <cpn :cmovies="movies" :cmessage="message"></cpn>
    </div>

    <template id="cpn">
        <div>
            <p>{{cmessage}}</p>
            <ul>
                <li v-for="item in cmovies">{{item}}</li>
            </ul>
        </div>
    </template>

    <script src="../vue.js"></script>
    <script>
        const app = new Vue({ //相当于父组件
            el: '#app',
            data: {
                message: 'vivian',
                movies: ['海贼王', '柯南', '火隐忍者', '蜡笔小新']
            },
            components: {
                cpn: { //子组件
                    template: '#cpn',
                    // 属性,里面是属性名
                    // 写法一:数组形式
                    // props: ['cmovies', 'cmessage']

                    //写法二:类型限制
                    // props: {
                    //     cmovies: Array,
                    //     cmessage: String
                    // }

                    //写法三:有默认值
                    props: {
                        //类型是对象或者数组时,默认值必须是一个函数
                        cmovies: {
                            type: Array,
                            default() {
                                return []
                            }
                        },
                        cmessage: {
                            type: String,
                            default: 'aaa',
                            required: true
                        }
                    }
                }
            }
        })
    </script>
</body>

在这里插入图片描述
注意:v-bind语法不支持驼峰命名法,要转成小写,例如childMyMessage要转成child-my-message才能使用v-bind

2. 子传父

子组件中,通过$emit来触发事件
父组件中,通过v-on来监听事件

<body>
    <!-- 父组件模板 -->
    <div id="app">
        <!-- 监听事件 v-on -->
        <cpn @itemclick="cpnClick"></cpn>
    </div>

    <!-- 子组件模板 -->
    <template id="cpn">
        <div>
            <button v-for="item in categories" @click="btnClick(item)">
                {{item.name}}</button>
        </div>
    </template>

    <script src="../vue.js"></script>
    <script>
        //子组件
        const cpn = {
            template: '#cpn',
            data() {
                return {
                    categories: [
                        { id: '111', name: '热门' },
                        { id: '222', name: '手机数码' },
                        { id: '333', name: '家用' }
                    ]
                }
            },
            methods: {
                btnClick(item) {
                    //发射事件:自定义事件
                    this.$emit('itemclick', item);
                }
            }
        }
        //父组件
        const app = new Vue({
            el: '#app',
            data: {

            },
            components: {
                cpn
            },
            methods: {
                cpnClick(item) {
                    console.log(item);
                }
            }
        })
    </script>
</body>

3. 父访问子

$children得到所有子组件,可以访问其中的属性和方法,但是对于获取第n个组件不那么方便
如:this.$children[0].showMessage();
$refs得到的对应ref名字的组件,可以访问特定的子组件,用得较多
如:this.$refs.aaa.showMessage();

4. 子访问父

$parent 访问父组件,但是一般不适用,组件耦合度高,不方便复用
例如:this.$parent.name
$root 访问根组件,也很少用
例如:this.$root.name

三、插槽slot

slot的目的:更具有扩展性,抽取共性,保留不同
在这里插入图片描述
基本使用:
<cpn><button slot="left">返回</button></cpn>
<slot name="left">默认值<slot>

编译作用域
举个例子,当父组件和子组件都有数据(data)isShowed时,在父作用域下(e.g. id=“app”)使用的isShowed会在父组件中找,在子作用域下(id=“cpn”)使用的isShowed会在子组件中找

作用域插槽
父组件对子组件展示数据的方式不满意,拿到子组件的数据进行展示

    <div id="app">
        <cpn></cpn>
        <cpn>
            <!-- 获得插槽对象命名为slot -->
            <temlate slot-scope="slot">
                <span v-for="item in slot.data">{{item}} - </span>
            </temlate>
        </cpn>
        <cpn></cpn>
    </div>

    <template id="cpn">
        <div>
            <!-- 插槽有一个数据data -->
            <slot :data="pLanguages">
                <ul>
                    <li v-for="item in pLanguages">{{item}}</li>
                </ul>
            </slot>
        </div>
    </template>

在这里插入图片描述

四、模块化开发

是为了解决多人开发下全局变量命名冲突的问题,还有js文件依赖的问题
常见的模块化规范:CommonJS、AMD、CMD、ES6的Modules
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值