Vue组件以及插槽

一、Vue组件

什么是组件:组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块。将来我们需要什么样的功能,就可以去调用对应的组件即可。
**重点:
**组件化和模块化的不同:
模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一
(高内聚,低耦合) 原理:
高内聚: 功能以及连接比较高的放在同一个js文件中,低耦合:让两个js文件互不影响
组件化:是从Ul界面的角度进行划分的;前端的组件化,方便UI组建的重用

全局组件定义的四种方式:

1、使用 Vue.extend 配合 Vue.component 方法:

<body>
    <!-- 第一种方法 -->
    <div id='app'>
        <!-- 函数调用的是自定义的名字 -->
        <login123></login123>
    </div>
    <script>
        //login999是变量的声明
        var login999 = Vue.extend({
            template:'<h1>登录</h1>'
        })
        // Vue.component 两个参数  参数1、自定义名字   参数2、声明的变量
        Vue.component('login123',login999)
    const vm = new Vue({
        el: '#app',
        data: {
        },
        methods: {
        }
    })
    </script>
</body>

2、直接使用 Vue.component 方法:

<body>
    <!-- 全局定义的第二种方法 -->
    <!-- 直接使用 Vue.component -->
    <div id='app'>
        <!-- 自定义的名字放在html中当标签使用 -->
        <login></login>
    </div>
    <script>
        // 两个参数  参数1、自定义名字(调用也是他)  参数2、一个对象里面有一个参数 template
        Vue.component('login',{
            template:'<h1>请登录</h1>'
        })
    const vm = new Vue({
        el: '#app',
        data: {
        },
        methods: {
        }
    })
    </script>
</body>

3、将模板字符串,定义到script标签种,同时,需要使用 Vue.component 来定义组件:

<body>
    <!-- 全局定义的第三种方法 -->
    <div id='app'>
        <!-- 自定义名字的调用 -->
        <name123></name123>
    </div>
    <!-- 模板类型 type='x-template'   定义标识符 id="tmpl"  产生关联 -->
    <script id="name" type="x-template">
        <div><a href="#">登录跳转</a></div>
    </script>
    <script>
        // 两个参数:1、自定义名字  2、对象  对象里面有一个模板参数主要是与模板类型里面的id='name'建立联系
        Vue.component('name123',{
            template:'#name'
        })
        const vm = new Vue({
            el: '#app',
            data: {
            },
            methods: {
            }
        })
    </script>
</body>

4、重点(常用)Vue.component(‘自定义名字’,{}) 可以定义 全局的还是私有的

注意:不能将HTML5的标签当作id ,只能包含一个根标签
注意:组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!

<body>
    <!-- 全局定义 -->
    <!-- <div id='app'>
        自定义的名字
        <name></name>
    </div>
    <template id="name">
        <div>
            11111
            <div>22222</div>
            <div>33333</div>
        </div>
    </template> -->
    <div id="app1">
        <name1></name1>
    </div>
    <template id="name1">
        <div>11111
            <div>22222</div>
            <div>33333</div>
        </div>
    </template>
    <script>
        // Vue.component('name',{
        //     template:'#name'
        // })
    const vm = new Vue({
        el: '#app1',
        data: {
        },
        methods: {
        },
        // 私有定义
        components:{
            name1:{
                template:'#name1'
            }
        }
    })
    </script>
</body>

5、组件化展示数据和响应事件

  • 在组件中,data需要被定义为一个方法
  • 在子组件中,如果将模板字符串,定义到了script标签中,
  • 那么,要访问子组件身上的data属性中的值,需要使用this来访问;

【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象
解释:数据隔离
避免组件被复用时,数据存在引用关系
使用component标签,来引用组件,并通过:is属性来指定要加载的组件:

    <style>
        #app{
            width: 600px;
            margin: auto;
        }
        .v-enter{
            transform: translateX(500px);
        }
        .v-enter-to{
            transform: translateX(0);
        }
        .v-enter-activeP{
            transition: all 2s;
        }
        .v-leave{
            transform: translateX(0);
        }
        .v-leave-to{
            transform: translateX(-500px);
        }
        .v-leave-active{
            transition: all 2s;
        }
    </style>
</head>
<body>
    <div id='app'>
        <button @click="flag">{{msg1}}</button>
        <!-- mode:只能用于组件 -->
        <!-- 使用component标签,来引用组件,并通过:is属性来指定要加载的组件: -->
        <!-- <component :is="flag?'login':'mine'"></component> -->

        <!-- <name123>{{msg1}}</name123> -->
        <transition mode="in-out">
            <!-- <name v-if="flag1"></name> -->
            <!-- <div v-if="flag1">1</div> -->
            <!-- <div v-else="flag1">2</div> -->
            <component :is="flag1? 'name':'name123'"></component>
            <!-- <name v-if="flag1"></name>
            <name123 v-else></name123> -->
        </transition>
        <transition mode="out-in">
            <!-- <name v-if="flag1"></name> -->
            <!-- <div v-if="flag1">1</div> -->
            <!-- <div v-else="flag1">2</div> -->
            <component :is="flag1? 'name':'name123'"></component>
          
        </transition>
        <transition mode="in-out">
            <name v-if="flag1"></name>
          
        </transition>
        <!-- <name123>{{msg1}}</name123> -->
    </div>
    <!-- 动画效果 -->
    <template id="name">
        <div>
            <button @click="add(1)">添加</button>
            <div>熬夜天数{{num}}</div>
            <div>{{msg}}</div>
        </div>
    </template>
    <tempalte id="name123">
        <div>
            减少
        </div>
    </tempalte>
    <script>
        Vue.component('name123',{
            template:'#name123'
        })
        Vue.component('name',{
            template:'#name',
            // 在组件中,data需要被定义为一个方法
            // 在子组件中,如果将模板字符串,定义到了script标签中,
            // 那么,要访问子组件身上的data属性中的值,需要使用this来访问;
            // 【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象
            // 解释:数据隔离
            data(){
                return{
                    msg:'今天不能睡!!',
                    num: null,
                }
            },
            methods:{
                add(number1){
                    if(this.num < 10){
                        this.num+=number1
                    }else{
                        alert('催死!!!')
                    }
                }
            }
        })
    const vm = new Vue({
        el: '#app',
        data: {
            flag1:true,
            msg1:'今晚早点睡'
        },
        methods: {
            flag(){
                this.flag1 = !this.flag1
            }
        }
    })
    </script>

6、组件化数据请求以及插槽的使用

mode:“out-in” 只能应用于组件,而HTML标签使用则不生效
插槽的使用
slot默认插槽
所谓具名插槽,顾名思义就是起了名字的插槽。有时我们需要多个插槽,例如当我们想使用某种通用模板:
例如:slot name = “name” 具名插槽(定义一个名字

插槽是什么?

插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。简单理解就是子组件中留下个“坑”,父组件可以使用指定内容来补“坑”。以下举例子帮助理解。

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- <script src="https://unpkg.com/vue-router@3.0.0/dist/vue-router.js"></script> -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <style>
        ul{
            display: flex;
            flex-wrap: wrap;
            justify-content: space-around;
            width: 1200px;
            margin: auto;
        }
        li{
            list-style: none;
            width: 18%;
        }
        img{
            width: 100%;
        }
        h2{
            text-align: center;
        }
    </style>
</head>
<body>
    <div id='app'>
        <course :type="type" page-size='10' page-num='1'>
            <!-- 具名插槽 -->
            <template v-slot:header>
                <h2>头部</h2>
            </template>
            <template v-slot:footer>
                <h2>底部</h2>
            </template>
        </course>
        <course :type="type1" page-size='5' page-num='1'></course>
        <course :type="type2" page-size='5' page-num='1'></course>
    </div>
    <template id="course_num">
        <div>
            <!-- 默认插槽 -->
            <slot></slot>
            <!-- 具名插槽 -->
            <slot name="header"></slot>
            <ul>
                <li v-for="(item,index) in list" :key="item.courId">
                    <img :src="item.coverFileUrl" alt="">
                    <div>{{item.courseTitle}}</div>
                    <div>共{{item.learningNum}}人</div>
                    <div v-if="item.isFree==1">免费</div>
                </li>
            </ul>
            <slot name="footer"></slot>
        </div>
    </template>
    <script>
        Vue.component('course',{
            template:'#course_num',
            props:{
                //可以定义多种类型
                // 自定义参数
                type:String,
                pageSize:[Number,String],
                pageNum:[Number,String]
                // pageNum:{
                //     type:Number,
                //     // default(){
                //     //     return 20
                //     // }
                // }
            },

            data(){
                return {
                    list:[],
                }
            },
            methods:{
                getList(type,pageSize,pageNum){
                    var url = new URLSearchParams()
                    url.append('type',type)
                    url.append('pageSize',pageSize)
                    url.append('pageNum',pageNum)
                    return axios.post('http://wkt.shangyuninfo.cn/weChat/applet/course/list/type',url)
                }
            },
            created(){
                console.log(this.type);
                this.getList(this.type,this.pageSize,this.pageNum).then(res=>{
                    console.log(res);
                    this.list = res.data.rows
                })
            }
        })
    const vm = new Vue({
        el: '#app',
        data: {
            type:'free',
            type1:'boutique',
            type2:'discount',
        },
        methods: {
        }
    })
    </script>
</body>

7、方法事件对象

<body>
    <div id='app'>
        <!-- 方法事件对象  $event -->
        <button @click="add(1,$event)">添加</button>
        {{num}}
    </div>
    <script>
    const vm = new Vue({
        el: '#app',
        data: {
            num:6,
        },
        methods: {
            add(num1,event){
                this.num+=num1
                console.log(event);
            }
        }
    })
    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值