Vue---组件

发布于:2024-04-29 ⋅ 阅读:(25) ⋅ 点赞:(0)

Vue—组件

定义组件

全局组件

  • vue2中template只能传递单标签,若要定义多个标签需要用div或其他包裹,vue3随意
<div id="app">
    <Child1></Child1>
</div>
Vue.component('Child1', {
    template: `
      <p>我是{{ name }}</p>
    `,
    data() {
        return {name: '组件1'}
    },
})

局部组件

局部组件在注册后只能在当前实例或者是组件中使用

  • 标签的命名只有首字母能大写,其余地方大写会直接报错
<div id="app2">
    <mydiv></mydiv>
</div>
// 写法1
const vm2 = new Vue({
    el: '#app2',
    components: {
        'mydiv': {
            template: `<p>我是{{ name }}</p>`,
            data() {
                return {name: '组件2'}
            }
        }
    }
})
// 写法2
let mydiv = {
    template: `<p>我是{{ name }}</p>`,
    data() {
        return {name: '组件2'}
    }
}
const vm2 = new Vue({
    el: '#app2',
    components: {
        mydiv
    }
})

组件通讯***重点***

在局部注册组件中我们是将组件注册到了vue根组件中,这里的根组件(**const vm2 = new Vue({})**这部分)也就是父组件,那么他和局部组件(子)传递数据的过程就叫组件通讯

<div id="app2"> // 父
    <mydiv></mydiv>	// 子
</div>

父子通信之父传子(props)

  • 自定义属性
  • 关键字props:通过 props,父组件可以向子组件传递数据,子组件可以接收父组件传递的数据并在内部使用
  • 案例中<qwe :name="info.name" :age="info.age"></qwe>的name和age其实就相当于是由props赋予的属性,因为在原根组件中是没有这两个属性的,他们是由props传递过来的
<div id="app">
    <qwe :name="info.name" :age="info.age"></qwe>
</div>
let qwe = {
    template: `
      <div>
        <p>你好</p>
        <p>{{ name }}</p>
        <p>{{ age }}</p>
      </div>
    `,
    props:['name','age']
}
const vm = new Vue({
    el: '#app',
    data: {
        info: {'name': '张三', 'age': 18}
    },
    components: {
        qwe
    }
})
  • props应传递字符串形式属性名,并且与data不要存在同名属性

image-20240428162406361

父子通信之子传父($emit)

  • 自定义事件
  • 关键字$emit:通过 $emit,子组件可以向父组件发送自定义事件,父组件可以监听这些事件并做出相应的处理
<div id="app">
    // getchild为自定义事件,用于子传父
    <child1 @getchild="handleGetChild"></child1>
    我儿子叫{{childname}}
</div>
var child1 = {
    template:
            `
              <button @click="handleSend">点我获得儿子</button>
            `,
    data() {
        return {'name': '张三'}
    },
    methods: {
        handleSend() {
            // 传递this.name给父组件,也就是'张三'
            this.$emit('getchild', this.name)
        }
    }
}
const vm = new Vue({
    el: '#app',
    data: {
        childname: ''
    },
    components: {
        child1
    },
    methods: {
        handleGetChild(info) {
            // info是子组件传递来的数据
            this.childname = info
        }
    }
})

image-20240428170445350

ref属性($refs)

  • $refs关键字:可以从子组件、父组件、任意其他组件中获取数据、调用函数

沿用上述示例:

<div id="app">
    // 新增绑定事件childRef
    <child1 @getchild="handleGetChild" ref="childRef"></child1>
    我儿子叫{{childname}}
</div>
var child1 = {
    template:
            `
              <button @click="handleSend">点我获得儿子</button>
            `,
    data() {
        return {'name': '张三'}
    },
    methods: {
        handleSend() {
            this.$emit('getchild', this.name)
        },
        sayHello(){
            console.log('你好')}
    }
}
const vm = new Vue({
    el: '#app',
    data: {
        childname: ''
    },
    components: {
        child1
    },
    methods: {
        handleGetChild(info) {
            // 打印子组件中的数据
            console.log(this.$refs.childRef.name)
            // 触发子组件中的函数satHello()
            this.$refs.childRef.sayHello()
            this.childname = info
        }
    }
})
  • 此时点击按钮后会在控制台打印’张三 你好’

动态组件

  • is关键字:可以接受一个组件名或对象,并根据该值渲染对应组件
<div id="app">
    <button @click="handleSwitch(1)">点我打开组件1</button>
    <button @click="handleSwitch(2)">点我打开组件2</button>
    <button @click="handleSwitch(3)">点我打开组件3</button>
    <components :is="current"></components>
</div>
var mydiv1 = {
    template:
        `
        <div>我是组件1</div>
        `
}
var mydiv2 = {
    template:
        `
        <div>我是组件2</div>
        `
}
var mydiv3 = {
    template:
        `
        <div>我是组件3</div>
        `
}
var vm = new Vue({
    el: '#app',
    data: {
        current: '',
        switchList: [mydiv1, mydiv2, mydiv3]
    },
    components: {
        mydiv1,
        mydiv2,
        mydiv3,
    },
    methods: {
        handleSwitch(s) {
            this.current = this.switchList[s - 1]
        }
    }
})

插槽

一般情况下,组件内的内容都是写死的,只能通过通信或修改组件本身,这导致其扩展性非常差,因此出现了插槽这一概念,只需在组件中添加<slot></slot>,就可以在body的组件标签中添加内容

<div id="app">
    <p>-----父组件开始-----</p>
    <mydiv></mydiv>
    <mydiv><button>来自插槽的按钮</button></mydiv>
    <mydiv>我是父组件,来占插槽的</mydiv>
    <p>-----父组件结束-----</p>
</div>
var mydiv = {
    template:
        `
        <div>
            <p>----插槽开始----</p>
            <slot></slot>
            <p>----插槽结束----</p>
        </div>
        `
}
var vm = new Vue({
    el:'#app',
    components:{
        mydiv
    }
})
  • 每个插槽都会接受父组件插入的所有数据
  • 当插槽未被使用时他会沿用上一个父组件
<div id="app">
    <p>-----父组件开始-----</p>
    <mydiv><button>来自插槽的按钮</button></mydiv>
    <p>-----父组件结束-----</p>
</div>
template:
`
<div>
<p>----插槽开始----</p>
<slot></slot>
<slot></slot>
<p>----插槽结束----</p>
</div>
`

image-20240428200902587

命名插槽

  • 命名插槽的好处,不会因为未使用插槽而自动填充
<div id="app">
    <p>-----父组件开始-----</p>
    <mydiv v-slot:a><button>来自插槽的按钮</button></mydiv>
    <p>-----父组件结束-----</p>
</div>
    var mydiv = {
        template:
            `
            <div>
                <p>----插槽开始----</p>
                <slot name="a"></slot>
                <slot name="b"></slot>
                <p>----插槽结束----</p>
            </div>
            `
    }
    var vm = new Vue({
        el:'#app',
        components:{
            mydiv
        }
    })

image-20240428201022376


网站公告

今日签到

点亮在社区的每一天
去签到