Vue入门到关门之组件

一、组件

1、什么是组件

在Vue.js中,组件是构建用户界面的可重用和独立的模块。每个Vue组件都封装了自己的模板、逻辑和样式,使得代码可以更加模块化、可维护性更高。通过组件化,你可以将界面拆分成独立的、可复用的部分,每个部分都有自己的功能和样式,这样可以更容易地管理复杂的界面,并且提高了代码的可读性和可维护性。

通俗来说,组件就是把一个很大的界面拆分为多个小的界面, 每一个小的界面就是一个组件,将大界面拆分成小界面就是组件化。而组件化开发指的就是根据封装的思想,把页面上可重用的 UI 结构封装为组件,从而方便项目的开发和维护。

在这里插入图片描述

2、组件的分类

  • 按作用范围分类
    • 全局组件:项目中所有地方都可以的组件称为全局组件
    • 局部组件(私有组件):仅有该组件才能使用的组件称为局部组件
  • 按照用途来分
    • 页面组件
    • 自定义组件

工程化开发之后:1个组件 就是1个xx.vue在vue 中规定:组件的后缀名是 .vue。之前接触到的 App.vue 文件本质上就是一个 vue 的组件。

以CSDN为例,如果使用组件化开发的话:

在这里插入图片描述

3、组件的内容

在Vue中,一个组件可以包括以下内容:

  1. **模板(Template):**定义了组件的结构和布局,使用HTML和Vue的模板语法来描述界面的外观。

  2. **脚本(Script):**包含了组件的逻辑,例如数据处理、事件处理、生命周期钩子等。通常使用JavaScript或TypeScript编写。

  3. **样式(Style):**定义了组件的样式,可以使用CSS、Sass、Less等来编写。

通过组件,你可以将页面划分成多个独立的部分,每个部分都有自己的功能和样式,并且可以在需要的地方进行重复使用。其中,每个组件中必须包含 template 模板结构,而 script 行为和 style 样式是可选的组成部分。

(1)template

  • 当前组件的DOM结构,需要定义到template标签的内部
template:`
  <div>
    <h1>{{ message }}</h1>
    <button @click="changeMessage">Change Message</button>
  </div>
`

注意:

  • template 是 vue 提供的容器标签,只起到包裹性质的作用,它不会被渲染为真正的 DOM 元素,后面的 v-slot 会使用到这个标签
  • template 中只能包含唯一的根节点

(2)script

  • 之后与组件相关的data数据、methods方法等,都需要定义到export default所导出的对象中
data() {
    return {
        message: 'Hello, Vue!'
    };
},
methods: {
    changeMessage() {
        this.message = 'Hello, World!';
    }
}

注意:

.vue 组件中的 data 必须是函数

vue 规定:.vue 组件中的 data 必须是一个函数,不能直接指向一个数据对象。

因此在组件中定义 data 数据节点时,下面的方式是错误的,但是在根组件这样写是可以的

data:{
    count:0
}

(3)style

  • 还是按照css的语法来写就好
<style>
h1 {
  color: blue;
}
</style>

总的来说,Vue组件是Vue.js框架中用于构建用户界面的独立模块,它们可以被组合和嵌套,从而构建出复杂的界面。

二、组件使用

1、全局组件

全局组件是在Vue应用程序中全局注册的组件,可以在应用的任何地方使用。一旦注册为全局组件,它就可以在整个应用程序中的任何Vue实例的模板中使用。

(1)注册全局组件

在Vue中,你可以使用Vue.component方法来注册全局组件。例如:

// 全局注册一个名为 'my-component' 的组件
Vue.component('my-component', {
  // ... 组件的选项
})

(2)使用全局组件

一旦注册为全局组件,你可以在任何Vue实例的模板中使用它:

<template>
  <div>
    <my-component></my-component>
  </div>
</template>

(3)完整示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>

</head>
<body>
<div id="app">
    <h1>全局组件的使用</h1>
    <button @click="handleClick">点我</button>


    <hr>
    <xiao></xiao>
    <hr>
    <h1>我是全局组件</h1>
    <xiao></xiao>
</div>
</body>
<script>
    // 1、定义全局组件
    Vue.component('xiao', {
        template: `<div>
            <h1>{{ name }}</h1>
            <button @click="handleClick">点我换名字</button>
          </div>`,
        data() {
            return {
                name: 'xiao'
            }
        },
        methods: {
            handleClick() {
                this.name = '彭于晏'
            }
        }
    })
    
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                alert('美女吧')
            }
        }
    })
</script>
</html>

2、局部组件

局部组件是在Vue实例(或者其他组件)的组件选项中注册的组件。它只能在注册它的实例或者组件内部使用。

(1)注册局部组件

在Vue实例或者其他组件中,你可以通过components选项来注册局部组件。例如:

<template>
  <div>
    <my-local-component></my-local-component>
  </div>
</template>

<script>
// 通过ES6的import将自定义的组件引入进来
import MyLocalComponent from './MyLocalComponent.vue';

export default {
  // 注册组件
  components: {
    'my-local-component': MyLocalComponent
  }
}
</script>

(2)使用局部组件

一旦在实例或者组件中注册了局部组件,你可以在该实例或者组件的模板中使用它:

<template>
  <div>
    <my-local-component></my-local-component>
  </div>
</template>

(3)完整示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>

</head>
<body>
<div id="app">
    <h1>局部组件的使用</h1>
    <button @click="handleClick">点我</button>
    <hr>
    <xiao></xiao>
</div>
</body>
<script>
    var xiao = {
        template: `
          <div>
            <h2>我是局部组件</h2>
          </div>
        `,
        data() {
            return {}
        },
        methods: {}
    }

    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                alert('美女吧')
            }
        },
        components: {
            xiao:xiao
        }
    })
</script>
</html>

3、全局和局部混合使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>

</head>
<body>
<div id="app">
    <h1>局部组件的使用</h1>
    <button @click="handleClick">点我</button>

    <hr>
    <child></child>
</div>
</body>
<script>
    var xiao = {
        template: `
          <div>
            <h2>我是局部组件</h2>
          </div>
        `,
        data() {
            return {}
        },
        methods: {}
    }

    //  全局组件
    Vue.component('child', {
        template: `
          <div>
            <h1>我是全局组件</h1>
            <xiao></xiao>
            <xiao></xiao>
            <xiao></xiao>
          </div>
        `,
        // 局部组件
        components: {
            // 第一种方法
            // xiao: {
            //     template: `
            //       <div>
            //         <h2>我是局部组件</h2>
            //       </div>
            //     `,
            //     data() {
            //         return {}
            //     },
            //     methods: {}
            // }

            // 第二种方法
            xiao
        }
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                alert('美女吧')
            }
        },
        components: {
            xiao
        }
    })
</script>
</html>

4、总结

  • 全局组件可以在整个应用程序中的任何地方使用,而局部组件只能在注册它的实例或者组件内部使用。
  • 全局组件适合用于在整个应用中频繁使用的通用组件,而局部组件适合用于特定页面或者组件内部的组件。
  • 全局组件的注册是通过Vue.component方法进行,而局部组件的注册是通过组件选项中的components属性进行。
  • 注意:组件中的数据,事件在没有额外参数的影响下都是独立的

了解elementui:

  • Element UI是一个基于Vue.js的组件库,提供了丰富的UI组件,如按钮、表格、弹窗等,可以帮助开发者快速构建美观、功能完善的前端界面。
  • 使用Element UI不仅可以减少开发工作量,而且它的组件都经过优化和测试,在性能和用户体验方面表现较好。
  • 通过引入Element UI的全局组件,开发者可以更加高效地开发出具有一致风格的界面。

三、组件间通信

在这里插入图片描述

1、父子通信之父传子-自定义属性

(1)父组件向子组件通信的步骤

  1. 在父组件中定义变量
data: {
    'url': './img/a.jpg'
}
  1. 把变量传递个子组件 ==> 自定义属性:myurl
<Child1 :myurl="url"></Child1>
  1. 在子组件中,拿到属性
props:['myurl']
  1. 以后在子组件中使用父组件的属性
this.myurl

(2)完整示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <h1>组件间通信之父传子:自定义属性</h1>
    <h2>父组件中的名字{{myname}}</h2>
    <div style="background-color: pink">
        <child :name="myname" yy="xx"></child>
    </div>
</div>
</body>
<script>
    // 全局组件
    Vue.component('child', {
        template: `
          <div>
            <h2>我是child组件</h2>
            <h3>父组件传递给子组件的{{ name }}---{{ yy }}</h3>
          </div>`,
        data() {
            return {}
        },
        props: ['name', 'yy']
    })

    var vm = new Vue({
        el: '#app',
        data: {
            myname: '彭于晏'
        },
    })
</script>
</html>

运行结果:

在这里插入图片描述

2、父子通信之子传父—自定义事件

(1)子组件向父组件通信的步骤

  1. 在父组件中定义变量,用来接收子组件传入的变量
data: {
    text:''
},
  1. 在父组件使用子组件时候,自定义事件 myevent,名字随便取
<Child1 @myevent="handleMyEvent"></Child1>
  1. 在父组件中定义函数,跟自定义事件绑定
handleMyEvent(childText){
    this.text=childText
}
  1. 在子组件中 ==> 触发自定义事件执行
this.$emit('自定义事件名字',this.mytext)

(2)完整示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <h1>组件间通信之子传父:自定义事件</h1>
    <h2>我是父组件</h2>
    子组件传给父组件的值===> {{p_name}}
    <hr>
    <div style="background-color:pink">
        <child @myevent="handleEvent"></child>
    </div>
</div>
</body>
<script>
    // 全局组件
    Vue.component('child', {
        template: `
          <div>
            <h2>我是child组件</h2>
            <input type="text" v-model="name">--> {{name}}
            <button @click="handleSend">传给父</button>
          </div>`,
        data() {
            return {
                name:''
            }
        },
        methods:{
            handleSend(){
                this.$emit('myevent',this.name)
            }
        }
    })

    var vm = new Vue({
        el: '#app',
        data: {
p_name:''
        },
        methods: {
            handleEvent(name){
                // name 是子组件中调用this.$emit('myevent',this.name)传过来的
                this.p_name = name
            }
        },
    })
</script>
</html>

运行结果:

在这里插入图片描述

3、ref属性(父子通信)

  • ref 是个属性, 如果在普通的DOM元素上,引用指向的就是该DOM元素;
  • 如果在子组件上,引用的指向就是子组件实例,然后父组件就可以通过 ref 主动获取子组件的属性或者调用子组件的方法

(1)放在普通标签上

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>

</head>
<body>
<div id="app">
    <h2>ref属性放在普通标签上</h2>
    <input type="text" v-model="name" ref="myinput">
    <img src="./img/2.jpg" alt="" ref="myimg">
    <button @click="handleClick">点我执行代码</button>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: ''
        },
        methods: {
            handleClick() {
                console.log(this.$refs)
                // 根据ref指定的名字,取出原生dom对象,然后就可以操作dom对象了
                var i = this.$refs['myinput']
                console.log(i)
                i.value = "你好"
                // 改图片
                var i = this.$refs['myimg']
                i.src = './img/3.jpg'
            }
        }
    })
</script>
</html>

(2)放在组件上

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <div style="background-color: antiquewhite">
        <h2>ref属性放在组件上</h2>
        <child ref="mychild"></child>
    </div>
</div>
</body>
<script>
    // 定义全局组件
    Vue.component('child', {
        template: `
          <div>
            <img :src="url" alt="">
            <button @click="handleClick('子组件传入的')">点我弹窗</button>
          </div>
        `,
        data() {
            return {
                url: './img/1.jpg'
            }
        },
        methods: {
            handleClick(name) {
                alert(name)
            }
        },
    })

    var vm = new Vue({
        el: '#app',
        data: {
            name: ''
        },
        methods: {
            handleClick() {
                // 操作组件对象
                var i = this.$refs['mychild']
                console.log(i.url)
                // 改图片
                i.url = './img/4.jpg'
                // 改执行方法
                i.handleClick('xiao')

                // 子传父
                this.name = i.url
            }
        }
    })
</script>
</html>

四、动态组件

1、概念

动态组件就是允许你根据当前的数据来动态地切换显示不同的组件。

  • Vue内部提供的组件component组件作用是:实现动态的渲染组件,按需显示组件。

  • component 标签是 vue 内置的,作用:组件的占位符

  • 其中is 属性的值,表示要渲染的组件的名字

  • is 属性的值,应该是组件在 components 节点下的注册名称

2、完整示例

  • 比如我们这里有三个组件,需求:在app根组件中点击不同按钮可以按需显示组件。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./vue/vue.js"></script>
    <style>
        .item {
            width: 150px;
            height: 50px;
            background-color: pink;
            font-size: 25px;
            margin: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .top {
            display: flex;
            justify-content: center;
        }
    </style>
</head>
<body>
<div id="app">
    <h1>动态组件</h1>
    <div class="top">
        <div class="item" @click="current='goods'">
            <span>商品</span>
        </div>
        <div class="item" @click="current='order'">
            <span>订单</span>
        </div>
        <div class="item" @click="current='user'">
            <span>用户</span>
        </div>
    </div>
    <div>
<!--        不使用动态组件-->
<!--        <goods v-if="current=='goods'"></goods>-->
<!--        <order v-else-if="current=='order'"></order>-->
<!--        <user v-else></user>-->

<!--        使用动态组件-->
        <component :is="current"></component>
    </div>
</div>
</body>

<script>
    // 1 定义出 商品,订单,用户 三个组件
    Vue.component('goods', {
        template: `<div>
                        <h3>商品页面</h3>
                        商品列表
                        <br>
                        商品列表
                    </div>`,
    })

    Vue.component('order', {
        template: `<div>
                        <h3>订单页面</h3>
                        订单内容
                    </div>`,
    })

    Vue.component('user', {
        template: `<div>
                        <h3>用户页面</h3>
                        用户信息
                    </div>`,
    })

    var vm = new Vue({
        el: '#app',
        data: {
            current: 'goods'
        },
    })
</script>
</html>

3、内部组件keep-alive组件的使用

  • keep-alive 会把内部的组件进行缓存,而不是销毁组件;

  • 在使用 keep-alive 的时候,可以通过 include 指定哪些组件需要被缓存;

  • 或者,通过 exclude 属性指定哪些组件不需要被缓存;但是:不要同时使用 include 和 exclude 这两个属性

<keep-alive exclude="goods">
     <component :is="current"></component>
</keep-alive>

五、插槽

1、介绍

slot的官方定义是用于组件内容分发,简单通俗的解释就是在组件化开发中,虽然组件是一样的,但是在不同的使用场景,组件的某一部分需要有不同的内容显示。slot就好比组件开发时定义的一个参数,如果不传入值就当默认值使用,如果传入了新值,在组件调用时就会替换定义时的slot默认值。

一般情况下,编写完1个组件之后,组件的内容都是写死的,需要加数据 只能去组件中修改,扩展性很差。然后就出现了插槽这个概念,只需在组件中添加<slot></slot>,就可以在body的组件标签中添加内容。

2、匿名插槽

  • 匿名插槽插入不同的内容类似for循环一样,使用插槽一次就要全部再来一遍,例如下面使用了两个不同内容但是匿名插槽一样,所以会有两次完整的组件形成。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>

</head>
<body>
<div id="app">
    <h1>插槽使用</h1>
    <div>
        <Home style="background-color:greenyellow">
            <div>
                <img src="./img/1.jpg" alt="">
            </div>
        </Home>
    </div>
    <hr>
    <div>
        <Home style="background-color:orange">
            <div>
                <img src="./img/2.jpg" alt="">
            </div>
        </Home>
    </div>
</div>
</body>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            who: 'Home'
        },
        components: {
            Home: {
                template: `<div>
                                <h3>我是首页</h3>
                                <slot></slot>
                                <h3>结束了</h3>
                        </div>`
            },
        }
    })
</script>
</html>

在这里插入图片描述

2、具名插槽

  • 在使用相同的具名插槽的时候,并没有再次形成完整的组件内容,而是将插槽里面的内容直接放到组件中对应插槽的位置
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <h1>插槽使用</h1>
    <div>
        <Home style="background-color:greenyellow">
            <div slot="middle">
                <img src="./img/1.jpg" alt="">
            </div>
            <div slot="middle">
                <img src="./img/1.jpg" alt="">
            </div>
            <div slot="bottom">
                <a href="">点我看mm</a>
            </div>
        </Home>
    </div>
    <hr>
</div>
</body>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            who: 'Home'
        },
        components: {
            Home: {
                template: `<div>
                                <h3>我是首页</h3>
                                <slot name="middle"></slot>
                                <h3>结束了</h3>
                                <slot name="bottom"></slot>
                        </div>`
            },
        }
    })
</script>
</html>

在这里插入图片描述

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值