Vue学习笔记(五)组件基础

28 篇文章 7 订阅

组件是Vue实例的重复使用,可以通过使用自定义标签在html中使用Vue实例

组件的创建


全局组件的创建

在全局中通过使用Vue.component()来创建组件,第一个参数传入一个字符串,表示该组件的名称,在html使用该名称作为自定义标签的标签名,第二个参数为一个对象,包括了组件的信息,模板,数据,方法等。

Vue.component("myCom", {
    template: '<h3>this is a component</h3>'
})

在html中使用该名称来作为自定义标签的标签名,要注意的是,如果该字符串中使用了驼峰式命名,如上面的myCom,在html中需要将大写字母转为小写字母并在其前加“-”,上面的组件在html这样使用

<my-com></my-com>

在页面中渲染后变为

<h3>this is a component</h3>

组件的模板也可以使用html中的某个结构,下面的组件使用了id为temp的html结构里的内容

<div id="app">
    <my-com></my-com>
</div>
<div id="temp">
    <h1>this is the template from temp</h1>
</div>
<script>
    Vue.component("myCom", {
        template: "#temp"
    })
</script>

要注意的是,template中只能有一个根元素,如果有两个根元素,那么会报错,如下面的情况,根元素有h3和p,所以最后会报错。

Vue.component("myCom", {
    template: '<h3>this is a component</h3><p>i am the second root</p>'
})

使用外部的结构也是一样的,为了防止报错,最好将外部引用的内容使用多一个div包裹,下面要传递的是一个h1标签和一个span标签,使用div包裹后可以顺利传递

<div id="temp">
    <div>
        <h1>this is the template from temp</h1>
        <span>i also come from temp</span>
    </div>
</div>

私有组件的创建

私有组件在Vue实例中的components创建,只能在该实例el属性对应的元素中使用

<div id="app">
    <app-com></app-com>
</div>
<script>
    let vm = new Vue({
        el: "#app",
        components: {
            appCom: {
                template: "<h1>this is the template from app</h1>"
            }
        }
    })
</script>

私有组件中也同样可以使用外部的html结构作为模板

<div id="app">
    <my-com></my-com>
</div>
<div id="temp">
    <h1>this is the template from temp</h1>
</div>
<script>
    let vm = new Vue({
        el: "#app",
        components: {
            appCom: {
                template: "<h1>this is the template from app</h1>"
            }
        }
    })
</script>

组件中data和methods的使用


data

组件中data的使用和Vue实例中data的使用有所不同,组件中的data为一个返回对象的方法,数据在返回的对象里面。

<div id="app">
    <my-com></my-com>
</div>
<script>
    Vue.component('myCom', {
        template: "<p>this is the template-------and data is :{{msg}}</p>",
        data: function() {
            return {
                msg: "this is the data of component"
            }
        }
    })
    let vm = new Vue({
        el: "#app"
    })
</script>

为什么data为一个返回对象的函数

如果组件的data为一个对象,那么就会导致使用该组件的Vue实例都共享同一个data

下面模仿一下使用data为一个对象的情况,点击按钮看看会发生什么情况

<div id="app">
    <my-com></my-com>
    <my-com></my-com>
    <my-com></my-com>
</div>
<div id="temp" style="display:none">
    <div>
        <input type="button" value="add" @click="count+=1">
        <p>{{count}}</p>
    </div>
</div>
<script>
    var myData = {
        count: 0
    }
    Vue.component('myCom', {
        template: "#temp",
        data: function() {
            return myData
        }
    })
    let vm = new Vue({
        el: "#app"
    })
</script>

我们会发现,不管我们点击哪一个按钮,都会导致所有的数字都加1,这就是组件共享一个data的后果,如果使用函数来返回对象就可以使每个组件都对应一个对象

<div id="app">
    <my-com></my-com>
    <my-com></my-com>
    <my-com></my-com>
</div>
<div id="temp" style="display:none">
    <div>
        <input type="button" value="add" @click="count+=1">
        <p>{{count}}</p>
    </div>
</div>
<script>
    Vue.component('myCom', {
        template: "#temp",
        data: function() {
            return {
                count: 0
            }
        }
    })
    let vm = new Vue({
        el: "#app"
    })
</script>

这里点击一个按钮只会影响同一个Vue实例下的count,不会影响其他的count

组件中的methods

组件中方法的使用和Vue实例中方法的使用是相同的

<div id="app">
    <app-com>
        </my-com>
</div>
<div id="temp" style="display:none">
    <input type="button" value="触发方法" @click="fn">
</div>
<script>
    let vm = new Vue({
        el: "#app",
        components: {
            appCom: {
                template: "#temp",
                methods: {
                    fn() {
                        console.log('fn');
                    }
                }
            }
        }
    })
</script>

父组件和子组件的传递


父组件向子组件传递值

父组件向子组件传递值需要通过v-bind(缩写为:)来将值绑定给自定义属性以传给子组件,子组件需要在其props数组中写入该自定义属性名(这里自定义属性如果为驼峰式命名,在html中要处理成以-连接的形式),子组件要使用该值时直接使用该自定义属性名

<div id="app">
    <my-com :parent-msg="msg"></my-com>
</div>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            msg: "--the value of parent--"
        },
        components: {
            myCom: {
                template: "<h1>the msg from parent is {{parentMsg}}</h1>",
                // props中的内容都是可读不可写的,在子组件中修改该值会报错
                props: ['parentMsg'],
                data: function() {
                    return {
                        //在父组件中传过来的名字在子组件中不能再次使用同名,否则会报错
                        // parentMsg: "the value of child"
                    }
                }
            }
        }
    })
</script>

父组件向子组件传递方法

与传递值使用v-bind来绑定相对应,传递方法时使用v-on(缩写为@)来绑定。在子组件中要调用父组件传过来的方法时,需要使用$emit方法来调用方法,其中第一个参数为父组件传过来的方法名,第二个为要传给该方法的参数。

<div id="app">
    <!-- 使用@来绑定 -->
    <my-com @func="show"></my-com>
</div>

<div id="temp" style="display:none">
    <button @click="childFn">触发事件</button>
</div>

<script>
    let vm = new Vue({
        el: "#app",
        methods: {
            show(data) {
                console.log(`this is the fn from parent ${data}`)
            }
        },
        components: {
            myCom: {
                template: "#temp",
                methods: {
                    childFn() {
                        //绑定方法  第二个参数起为方法的参数
                        this.$emit('func', '子组件中的参数')
                    }
                }
            }
        }
    })
</script>

动态组件


如果在某个位置要实现多个组件的选择使用,就要用到动态组件了,如果只有两个选择时,我们可以使用v-if和v-else来完成动态组件的实现。

<div id="app">
    <input type="button" value="first" @click="flag=true">
    <input type="button" value="second" @click="flag=false">
    <app-com1 v-if="flag"></app-com1>
    <app-com2 v-else></app-com2>
</div>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            flag: true
        },
        components: {
            appCom1: {
                template: "<p>this is the first template</p>"
            },
            appCom2: {
                template: "<p>this is the second template</p>"
            }
        }
    })
</script>

但是如果是三个甚至以上的选择组件的话,这么实现就不太现实了,这个时候我们可以使用Vue的<component>元素和v-bind绑定的is属性来实现动态组件

在data中使用一个属性来存储要选择的组件名,is属性对应的值则为要使用的组件的名称,通过改变存储的组件名就可以实现动态组件

<div id="app">
    <button @click="name='first'">first</button>
    <button @click="name='second'">second</button>
    <button @click="name='third'">third</button>
    <component :is="name"></component>
</div>

<script src="lib/vue.js"></script>
<script>
    Vue.component("first", {
        template: "<h1>this is the first template</h1>"
    })

    Vue.component("second", {
        template: "<h1>this is the second template</h1>"
    })

    Vue.component("third", {
        template: "<h1>this is the third template</h1>"
    })

    let vm = new Vue({
        el: "#app",
        data: {
            name: "first"
        }
    })
</script>

Vue实例中操作DOM和组件


Vue实例中操作DOM

Vue中建议不直接操作DOM,但是如果需求中需要我们对DOM进行操作或者获取DOM元素的内容,我们可以使用ref属性来实现。使用了ref属性的元素,其DOM对象会储存在其所在的Vue实例中的$refs对象中,通过ref属性对应的值来调用该对象。

<div id="app">
    <input type="button" @click="getEl" value="按钮">
    <h1 ref="myh1">i am the msg in h1</h1>
</div>

<script>
    let vm = new Vue({
        el: "#app",
        methods: {
            getEl() {   
                // this.$refs.myh1是一个DOM对象
                console.log(this.$refs.myh1.innerHTML)
            }
        }
    })
</script>

Vue实例中操作组件

Vue实例中操作组件与操作DOM类似,都要用到ref属性,通过这种方式,可以在父组件中调用子组件中的方法,下面的代码中,在按下父组件按钮时,同时会触发子组件的方法。

<div id="app">
    <input type="button" @click="getEl" value="父组件按钮">
    <h1 ref="myh1">i am the msg in h1</h1>
    <login ref="childTemp"></login>
</div>


<div id="temp" style="display:none">
    <input type="button" @click="show" value="子组件按钮">
</div>

<script>
    let vm = new Vue({
        el: "#app",
        methods: {
            getEl() {
                // this.$refs.myh1是一个DOM对象
                console.log(this.$refs.myh1.innerHTML)
                    //调用子组件的方法
                this.$refs.childTemp.show()
            }
        },
        components: {
            login: {
                template: "#temp",
                methods: {
                    show() {
                        console.log('here is the child template')
                    }
                }
            }
        }
    })
</script>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值