Day 05 Vue---组件

Day 05 Vue—组件

from

一、组件

1、组件是什么?有什么用

组件类似于django模板语言中的include,用来扩展HTML元素,封装可用代码,目的是复用

-------例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
-------组件把js,css,html放到一起,有逻辑,有样式,有html

2、组件注册方式

2.1 全局组件

定义方式是用Vue对象创建一个新的component

<script>
    //没有代码提示,语法检查,目前这么用
    //后面会使用webpack打包,直接定义成 xx.vue文件,通过webpack打包
    Vue.component('global',{  // 全剧组件名 + 组件内容
        template:`
        
我是NavBar
`
, methods:{ handleClick(){ console.log('nav nav') } } }) var vm = new Vue({ el: '#box', data: { }, })
script>
2.2 局部组件

局部组件是只能在局部使用的组件,在当前页面的Vue下的components中–放在 Vue实例(根组件) 中

<script>
 let vm = new Vue({
        el: '#box',
        data: {},
        // 创建1个组件对象(局部组件)
        components: {
            local: {    // local 组件名
                template: `
                    
我是局部组件
`
, // 组件的模板 methods: { handleClick() { console.log('我被点击了') } } } }
script>

3、组件使用方式

组件的使用方式非常简单,创建一个同名的标签就好了

<div id="box" style="max-width: 300px">
    <local>local>
    <global>global>
div>

注意点:

  • 定义的组件(body中的位置)必须要放在Vue实例(这也是一个组件 根组件)中
  • 局部组件 必须放在 全局组件/根组件 中,无法单独使用

二、组件编写方式和Vue实例的区别

1 自定义组件需要有一个root element,一般包裹在一个div中
2 父子组件的data是无法共享
3 组件可以有data,methods,computed…,但是data 必须是一个函数

1、Vue实例(其实,它也是1个组件,是1个根组件)


<html lang="en">
<head>
  <meta charset="UTF-8">
  <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
  <title>Titletitle>
head>

<div id="box">
  <ul>
    <li>姓名:{{name}}li>
    <li>年龄:{{age}}li>
    <li><button @click="handleClick">Test Buttonbutton>li>
  ul>
div>

<body>


<script>
  let vm = new Vue({
    el:'#box',
    data:{
      name:'Super',
      age:99
    },
    methods:{
      handleClick(){
        alert('按钮被点击!')
      }
    }
  })
script>
body>

html>

2、组件


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>局部组件title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>
    
<div id="box" style="max-width: 300px">
    <ul>
        <li v-for="i in 3">
            <global>global>
        li>
    ul>
div>
    
body>
<script>
    // 创建1个组件对象(全局组件)
    Vue.component('global', {
        template: `
            
我是全局组件

`
, // 创建1个组件对象(局部组件) components: { local: { template: `
我是局部组件
`
, } } }) let vm = new Vue({ el: '#box', })
script> html>

3、区别

3.1 自定义组件需要有1个 root element,一般包裹在 1个div

Day 05 Vue---组件_第1张图片

3.2 父子组件的data是无法共享的
  • 这一点就像Docker的容器一样,是相互隔离
  • 就算父子的data中数据相同,拥有相同的方法,也是互不影响
3.3 组件可以有data、methods、computed…,但是 data 必须是一个函数Vue实例:data是1个键值对,用来存放属性的
var vm = new Vue({
    el: '#box',
    data: {
        isShow: true
    }
})
组件:data是1个函数,需要有返回值(return)
Vue.component('global', {
    template: `
        
我是头部组件
显示消失
`
, methods: { handleClick() { console.log('我被点击了') this.isShow = !this.isShow } }, data() { return { isShow: true } } })

三、组件通信

介绍组件间的通信必须要介绍props组件

props是组件中非常重要的一个选项。在 Vue 中,父子组件的关系可以总结为 props down, events up父组件通过 props 向下传递数据给子组件子组件通过 events父组件发送消息。

Day 05 Vue---组件_第2张图片

1、父传子

1.1 静态props

静态Prop通过为子组件在父组件中的占位符添加特性的方式来达到传值的目的

子组件要显式地用 props 选项声明它期待获得的数据

  Vue.component("global", {
    template: `
                <div>
                <div style="background: rgba(255,104,104,0.7); padding: 5px;">全局组件/子组件div>
                {{desname}}  // 显式调用
                {{desage}}
            div>
    `,
    props:['desname', 'desage']
  });
1.2命名约定(我没有遵守)
  • 对于props声明的属性来说,在父级HTML模板中,属性名需要使用中划线写法
  • 子级props属性声明时,使用小驼峰或者中划线写法都可以;而子级模板使用从父级传来的变量时,需要使用对应的小驼峰写法

image-20201217194038113

1.3 动态props

在模板中,要动态地绑定父组件的数据到子模板的 props,与绑定到任何普通的HTML特性相类似,就是用 v-bind。每当父组件的数据变化时,该变化也会传导给子组件

因为v-bind='变量名'所以我们传递的其实是父组件的变量

Day 05 Vue---组件_第3张图片

1.4 props验证

验证传入的 props 参数的数据规格,如果不符合数据规格,Vue 会发出警告。

能判断的所有种类(也就是 type 值)有:
String, Number, Boolean, Function, Object, Array, Symbol

2、子传父(通过事件方式)

点击子组件,就会触发父组件的某个函数执行

子组件向父组件传值,同样的他们之间的契合点也是子组件引入的地方。
首先来到子组件,用$emit发射数据
Day 05 Vue---组件_第4张图片
然后再来到父组件,在契合点的地方
Day 05 Vue---组件_第5张图片

子组件传参

方法一

子组件传出单个参数时:

1 // 子组件
            handleNav() {
                console.log('我是子组件的函数')
                this.$emit('my_event', 666, 777, this.name)
            }

3 // 父组件
            handleClick(a,b,c) {
                console.log('我是父组件的函数')
                console.log(a)
                console.log(b)
                console.log(c)
            }
方法二

子组件传出多个参数时:

1 子组件
      handleNav() {
        console.log('我是子组件的函数')
        this.$emit('my_event', 666, 777, this.name)
      }
    
    
3 父组件 arguments 是以数组的形式传入
    methods: {
      handleClick(arguments) {
        console.log(arguments)
      }

四、ref属性

1、父传子

ref放在标签上,拿到的是原生的DOM节点
ref放在组件上,拿到的是组件对象
通过这种方式实现子传父(this.$refs.mychild.text)
通过这种方式实现父传子(调用子组件方法传参数)


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子传父title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>

<div id="box">
    <input type="text" ref="myRef">
    <button @click="handleButton">点我button>
div>

body>
<script>
    // 创建1个组件对象(全局组件/子组件)
    Vue.component('global', {
        template: `
            
`
, data() { return { myText: '' } }, methods: { handleClick() { this.$emit('my_event', this.myText) this.$emit('my_event', this.innerHTML) } } }) // 父组件 let vm = new Vue({ el: '#box', data: { name: '' }, methods: { handleShow(a) { this.name = a }, handleButton() { console.log(this.$refs) console.log(this.$refs.myRef) console.log(this.$refs.myRef.value) } } })
script> html>

2、父传子 直接赋值

<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>子传父title>
  <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>

<div id="box">

  <global @my_event="handleClick(arguments)"  ref="global">global>
div>

body>
<script>
  // 创建1个组件对象(全局组件/子组件)
  Vue.component("global", {
    template: `
      
全局组件/子组件{{child_name}}
`
, data() { return { child_name: "" }; }, methods: { handleNav() { console.log("我是子组件的函数"); this.$emit("my_event", 666, 777, this.name); } } }); // 父组件 let vm = new Vue({ el: "#box", data: { name: "xxxx" }, methods: { handleClick() { this.$refs.global.child_name=this.name console.log(this.$refs.global); } } });
script> html>

五、事件总线

Day 05 Vue---组件_第6张图片


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子传父title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>

<div id="box">
    <global1>global1>
    <hr>
    <global2>global2>
div>

body>
<script>
    // 定义1个时间总线
    let bus = new Vue({})

    // 组件1
    Vue.component('global1', {
        template: `
            

组件1

`
, data() { return { myText: '' } }, methods: { handleClick1() { console.log(this.myText) bus.$emit('any', this.myText) // 通过事件总线发送 } } }) // 组件2 Vue.component('global2', { template: `

组件2

收到的消息是:{{recvText}}
`
, data() { return { recvText: '' } }, mounted() { // 组件的挂载(生命周期钩子函数中的1个),开始监听时间总线上的:any bus.$on('any', (item) => { console.log('收到了', item,) this.recvText = item }) }, methods: {} }) // 父组件 let vm = new Vue({ el: '#box', data: {}, })
script> html>

HTML

复制

[Day 05 Vue---组件_第7张图片](https://gitee.com/xuexianqi/img/raw/master/img/13 bus.gif)

四:动态组件

1.基本使用


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动态组件title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>

<div id="box">
    <ul>
        <li>
            <button @click="who='child1'">首页button>
        li>
        <li>
            <button @click="who='child2'">订单button>
        li>
        <li>
            <button @click="who='child3'">商品button>
        li>
    ul>
    <component :is="who">component>
div>

body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            who: 'child1'
        },
        components: {
            child1: {
                template: `
                    
我是首页
`
, }, child2: { template: `
我是订单
`
, }, child3: { template: `
我是商品
`
, } } })
script> html>

HTML

复制

[Day 05 Vue---组件_第8张图片](https://gitee.com/xuexianqi/img/raw/master/img/16 dynamic01.gif)

2.keep-alive的使用

keep-alive可以让输入框内有的内容一致保持,不会因为切换而重置


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="js/vue.js">script>
head>
<body>

<div id="box">
    <ul>
        <li>
            <button @click="who='child1'">首页button>
        li>
        <li>
            <button @click="who='child2'">订单button>
        li>
        <li>
            <button @click="who='child3'">商品button>
        li>
    ul>
    <keep-alive>
        <component :is="who">component>
    keep-alive>
div>

body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            who: 'child1'
        },
        components: {
            child1: {
                template: `
                    
我是首页
`
, }, child2: { template: `
我是订单
`
, }, child3: { template: `
我是商品
`
, } } })
script> html>

HTML

复制

[Day 05 Vue---组件_第9张图片](https://gitee.com/xuexianqi/img/raw/master/img/17 dynamic02.gif)

五:slot 插槽

1.基本使用


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>slot 插槽title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>

<div id="box">
    <child>
        <h6>Hello Worldh6>
    child>
div>

body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            who: 'child1'
        },
        components: {
            child: {
                template: `
                    
我是组件的原内容
`
, }, } })
script> html>

HTML

复制

Day 05 Vue---组件_第10张图片

2.小案例(通过插槽实现在1个组件中控制另1个组件的显示隐藏)


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>slot 插槽title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>

<div id="box">
    
    <child1>
        <button @click="isShow=!isShow">显示/隐藏组件2button>
    child1>

    <child2 v-if="isShow">child2>
div>
body>
<script>
    Vue.component('child1', {
        template: `
组件1
`
, }) Vue.component('child2', { template: `

组件2

`
, }) var vm = new Vue({ el: '#box', data: { isShow: true } })
script> html>

HTML

复制

[Day 05 Vue---组件_第11张图片](https://gitee.com/xuexianqi/img/raw/master/img/15 slot1.gif)

3.具名插槽


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>具名插槽title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js">script>
head>
<body>

<div id="box">
    
    <child>
        <p slot="a">我是具名插槽a插入的内容p>
        <div slot="b">我是具名插槽b插入的内容div>
    child>
div>
body>
<script>
    Vue.component('child', {
        template: `

我是组件的原内容
`
, }) var vm = new Vue({ el: '#box', data: {} })
script> html>

HTML

复制

可以指定标签放在某个插槽的位置

Day 05 Vue---组件_第12张图片

你可能感兴趣的:(Vue,vue,dom)