Vue -组件、组件传值、插槽

一、组件的写法-组件模板的分离写法

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

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

<!--template标签-->
<template id="cpn">
  <div>
    <h2>{{title}}</h2>
    <button @click="btnClick">click</button>
  </div>
</template>

<script src="../js/vue.js"></script>
<script>
  //子组件中也有data,method 属性
  const cpn = {
    template: '#cpn',
    data() {
      return {
        title: 'dc'
      }
    },
    methods:{
      btnClick(){
        console.log('click');
      }
    }
  }
  // 注册一个全局组件
  /*Vue.component('cpn', {
    template: '#cpn'
  })*/
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    // 注册一个局部组件
    components:{
      cpn
    },
    //可以用template属性直接替换el内容
    //template:'<cpn/>'
  })
</script>

</body>
</html>

为什么data在组件中必须是一个函数呢?

原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

二、父向子组件传值-props ;子向父传值用-emit

 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
        <div id='app'>
            <!-- 父组件传值用props,子组件传值用v-on -->
            <cpn :cmessage="message" :cmovie="movies" :cinfo="info" @item-click="cpnClick"></cpn>
        </div>
        <template id="cpn">
            <div>
                <h2>{{cmessage}}</h2>
                <ul>
                    <li v-for="item in cmovie">{{item}}</li>
                </ul>
                <h2>{{cmovie}}</h2>
                <h2>{{cinfo}}</h2>
                <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
            </div>
        </template>
        <script>
            //组件构造器
            const cpn = {
                template: '#cpn',
                //props:['cmessage','cmovie'],//组件传值
                /* props:{
                    cmessage:String,
                    cmovie:Array
                } */
                //提供一些默认值, 以及必传值
                props:{
                    cmessage:{
                        type:String,
                        default:'aaaaa',
                        required:true
                    },
                    // 类型是对象或者数组时, 默认值必须是一个函数
                    cmovie:{
                        type: Array,
                        default() {
                          return []
                        }
                    },
                    cinfo:{
                        type:Object,
                        default(){
                            return {}
                        }
                    }
                },
                //组件中的数据要用return 防止重复
                data() {
                    return {
                        title: 'dc',
                        categories:[
                            {id:'aaa',name:'热门推荐'},
                            {id:'bbb',name:'手机数码'},
                            {id:'ccc',name:'家用家电'}
                        ]
                    }
                },
                methods:{
                    btnClick(item){
                        //console.log(item);
                        //子组件向父组件传值 发射事件
                        this.$emit('item-click',item)
                    }
                }
            }
            //注册全局组件
        /*     Vue.component('cpn', {
                template: '#cpn',
                data() {
                    return {
                        title: 'abc'
                    }
                }
            }) */
            const app = new Vue({
                el: '#app',
                data: {
                    message: 'nishao',
                    movies:['速度与激情','海贼王'],
                    info:{
                        name:'zhangsan',
                        age:18
                    }
                },
                //注册局部组件
                components:{
                    cpn
                },
                methods:{
                    cpnClick(item){
                        console.log('cpnClick',item)
                    }
                }
                /* template:`<h1>nihaoa1</h1>` */
            })
        </script>
    </body>
</html>

三、插槽-slot

在子组件中,使用特殊的元素<slot>就可以为子组件开启一个插槽。
该插槽插入什么内容取决于父组件如何使用。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
        <div id="app">
            <cpn>slot test</cpn>
            <cpn><button slot="left">left</button></cpn>
            <cpn><button slot="center">center</button></cpn>
            <cpn><button slot="right">right</button></cpn>
        </div>
        <template id="cpn">
            <div>
                <h3>组件</h2>
                <!-- <slot>中的内容表示,如果没有在该组件中插入任何其他内容,就默认显示该内容-->            
                <slot><button>按钮</button></slot>
                <slot name="left"><span>左边</span></slot>
                <slot name="center"><span>中间</span></slot>
                <slot name="right"><span>右边</span></slot>
            </div>
        </template>
        <script>
            const app = new Vue({
                el:"#app",
                data:{
                    message:'nihao'
                },
                components:{
                    cpn:{
                        template:'#cpn'
                    }
                }
            })
        </script>
    </body>
</html>

 

posted on 2021-06-30 16:08  TrustNature  阅读(189)  评论(0编辑  收藏  举报