Vue(二)

79 阅读2分钟

组件

定义:一段封装了html css的代码

组件的两种注册方式

全局变量

Vue.component("组件名",{
  template:"html代码"data(){
      
    },
    methods:{
      
    },
    computed:{
      
    },
    watch:{
      
 })
<div id="app">
        <my-com></my-com>
    </div>
    <script>
        Vue.component("myCom",{
            template:`<div>
                        <h1>我是一个组件</h1> 
                        <a>百度一下,你就知道</a>       
                    </div>`
        })

        new Vue({
            el:"#app"
        })
    </script>

局部注册

可以同时在局部注册多个组件,组件之间也可以调用,但是记得要注册

var head = {
            template: `<div><h1 >{{msg}}</h1></div>`,
            data: function () { return { msg: "我是头部" } },
        }

new Vue({//根实例,是最大的组件
            el: "#app",
            data: {},
            components: {
                myhead:head,//组件名:组件配置项
            }
        })
 <div id="app">
        <my-com></my-com>
        <my-com></my-com>//可以复用
    </div>
    <script>
       const myCom={
        template:`<div>
                    <h1>{{msg}}</h1>
                    <h2>{{gender}}</h2>
                </div>`,
        data(){
            return{
                sex:1,
                msg:"我是局部注册的第一个组件"
            }
        },
        computed:{
            gender(){
                return this.sex==1?"男":"女"
            }
        }
    }
    	 const myCom1={
        template:`<div>
                    <h1>{{msg}}</h1>
                    <h2>{{gender}}</h2>
                </div>`,
        data(){
            return{
                sex:1,
                msg:"我是局部注册的第二个组件"
            }
        },
        computed:{
            gender(){
                return this.sex==1?"男":"女"
            }
        }
    }
    new Vue({
            el: "#app",
            data: {},
            components: {
               myCom
            }
        })
    </script>

注意:

  1. 没有挂载点
  2. 多了一个template属性,是放html结构的
  3. 组件必须得有template
  4. 组件标签只能有一个根节点,最外层要由一个大的div包裹
  5. 组件名在js中是使用驼峰式,在html中改为以横线连接的小写字母
  6. 组件中的data必须是函数,并且必须要return一个对象,就是我们的数据对象

组件之间的传值

组件之间传值的三种情况:

1.父- 子 props

2.子 -父 自定义事件

3.同级:先子给父,再父给子

父-子传值:props(属性)

注意:子组件不允许直接修改父组件传入的属性,如果需要更新(更改)这个属性,只能让父组件重新传

用法:

1.子组件内部要接收属性并规定属性的使用场景

2.父组件中使用子组件要给属性传实际的数据

子父传值:

<div id="app">    
    <my-com :a="msg" :b="change" :c="arr"></my-com>
</div> 
<script> 
    const myCom={
        props:["a","b","c"],//子组件内部接收的属性
        template:`<div>
                        //规定属性的使用场景
                    <h1 @click="b">我是组件:{{a}}</h1>
                    <ul>
                        <li v-for="item in c">{{item}}</li>    
                    </ul>
                  </div>`,
    }
    new Vue({
        el:"#app",
        data:{
            box:"welcome",
            msg:"我是父组件的数据",
            info:"哈哈",
            arr:[1,2,3,4]
        },
        methods:{
            change(){
                console.log(this)
            }
        },
        components:{
           //组件名:组件配置项
           myCom
        }

    })

子父孙传值:

<div id="app">

    <my-com :a="msg"></my-com>
</div>
<script>
    const child={
        props:["b"],
        template:`<h1>我是孙子组件:{{b}}</h1>`
    }
    const myCom={
        props:["a"],
        template:`<div>
                <h1>我是子组件:{{a}}</h1>
                <child :b="a"></child>
            </div>`,
        data(){
            return{
                info:"我是子组件的数据"
            }
        },
        components:{
            child
        }
    }
    new Vue({
        el:"#app",
        data:{
            msg:"我是父组件的数据"
        },

        components:{
            myCom
        },
    })
</script>

子-父:自定义事件

子父传值:定义事件

<div id="app"> 
        <h1 >我是父组件{{msg}}</h1> 
       <child @abc="fn"></child>
    </div> 
<script>
const child={
            data(){
                return{
                    info:"我是子组件的数据"
                }
            },
            template:`<h1 @click="change">我是子组件</h1>`,
            methods:{
                change(){
              //$emit用于主动触发绑定在本组件标签上的自定义事件
              //$emit(自定义事件名,参与方法的参数)
                    this.$emit("abc",this.info)
                }
            }
        }
        new Vue({
            el:"#app",
            data:{
                msg:""
            },
            components:{
                child
            },
            methods:{
                fn(m){
                  this.msg=m
                }
            }
        })
</script>

插槽

插槽:其实就是给组件标签中的内容(可以是多个标签)预留的位置。如果组件模板中有多个插槽,那么组件标签的内容将会复制,插入到多个插槽中

普通插槽

<div id="app" >
        <my-head>
            <h1>hello</h1>
        </my-head>
    </div>
    <script>
        var head = {
            template: `<div>
                            //插槽,可以把html里的h1标签渲染到页面上
                            <slot></slot>
                            <h1 >{{msg}}</h1>
                       </div>`,
            data: function () { return { msg: "我是头部" } },
        }
        new Vue({
            el:"#app",//挂载点
            components:{
                myHead:head
            }
        })
    </script>

具名插槽(v-slot:可以缩写为#)

给插槽取名字

<body>
    <div id="app" >
        <my-head>
            <template v-slot:before> <!--v-slot:可以缩写为#-->
                <h1>hello</h1>
            </template>
            <template #after>
                <h1 >world</h1>
            </template>
            
        </my-head>
    </div>

    <script>
        var head = {
            template: `<div>
                            <slot name="before"></slot>
                            <h1 >{{msg}}</h1>
                            <slot name="after"></slot>
                       </div>`,
            data: function () { return { msg: "我是头部" } },
        }
        new Vue({
            el:"#app",//挂载点
            components:{
                myHead:head
            }
        })
    </script>
</body>

编译作用域

如果插槽模板中想使用该组件内部的数据,首先需要在模板的插槽中定义v-bind:属性=“数据”

组件调用的地方插槽通过 v-slot:属性=“prop”   prop拿到的不是一个,代表所有属性的集合

<body>
    <div id="app">
        <mycom>
            <template #before="{abc}">//解构赋值
                <h1>{{abc}}</h1>
            </template>
            <template #after="props">
                <p>{{props.efg}}</p>
            </template>
            <template #middle>
                <h3>就是开心</h3>
            </template>

        </mycom>
    </div>
    <script>
        const mycom = {
            data(){
                return{
                    msg:"我是子组件的数据1",
                    info:"我是子组件的数据2"
                }
            },
            template: `
                <div>
                    <h1>我是组件</h1> 
                    <slot name="before" v-bind:abc="msg" ></slot>
                    <ul>
                        <slot name="middle"></slot> 
                        <li>1</li>   
                        <li>2</li>    
                    </ul>  
                    <slot name="after" v-bind:efg="info"></slot> 
                </div>
            `
        }
        new Vue({
            el: "#app",
            components: {
                mycom
            },
            data:{
                msg:"我是父组件"
            }
        })
    </script>
</body>

组件的声明周期

生命周期:组件从创建到销毁的完成过程

生命周期(钩子)函数:在特定的时间节点会自动触发的函数

  beforeCreate(){
    console.log("组件创建之前")
  },
  created(){
    console.log("组件创建完毕")
  },
  beforeMount(){
    console.log("组件渲染前/组件挂载前")
  },
  mounted(){
    //这个阶段我们能看到组件渲染在页面上
    console.log("组件挂载完毕")
  },  
  beforeUpdate(){
    //首次不触发,页面重新渲染的时候触发
    //子组件用到的属性渲染到了视图中的时候触发(视图是否更新)
    console.log("组件更新前")
  },
  updated(){
    console.log("组件更新后")
  },
  beforeDestroy(){
    console.log("组件销毁前")
  },
  destroyed(){
    console.log("组件销毁后")
  },

动态组件

<div id="app">
        <component v-bind:is="title"></component>
        <button @click="change(2)">按钮</button>
    </div>
    <script>
        var coma1 = {
            template: `<div><h1>我是第一个组件</h1></div>`,
        }
        var coma2 = {
            template: `<div><h1>我是第二个组件</h1></div>`,
        }
        var coma3 = {
            template: `<div><h1>我是第三个组件</h1></div>`,
        }
        new Vue({
            el: "#app",
            data: {
                tab: "mycom",
                title:"mycom"
            },
            components: {
                coma1,
                coma2,
                coma3,
            },
            methods:{
                change(n){
                    this.title="mycom"+n
                }
            }
        })
    </script>