【Vue】Vue组件--上

目录

一、组件基础

二、组件的嵌套关系

[1. 基础架构](#1. 基础架构)

[2. 嵌套](#2. 嵌套)

三、组件注册方式

[1. 局部注册:](#1. 局部注册:)

[2. 全局注册:](#2. 全局注册:)

四、组件传递数据

[1. 基础架构](#1. 基础架构)

[2. 传递多值](#2. 传递多值)

[3. 动态传递数据](#3. 动态传递数据)

五、组件传递多种数据类型

[1. Number](#1. Number)

[2. Array](#2. Array)

[3. Object](#3. Object)

六、组件传递Props的校验

[1. 默认值](#1. 默认值)

[2. 必选项](#2. 必选项)


一、组件基础

组件最大的优势就是可复用性

当使用构建步骤时,我们一般将vue组件定义在一个单独的.vue文件当中,这就被叫做单文件组织(SFC)

组件组成结构 ----> 在components文件当中新建文件MyApp.vue

html 复制代码
<template>
    <div class="container">{{ message }}</div>
</template>
<script>
    export default{
        data(){
            return{
                message:'组件基础组成'
            }
        }
    }
</script>
<!-- 让当前样式只在当前组件中生效 ,如果不加scoped那么.container将会是全局样式在任何组件当中使用-->
<style scoped>
    .container{
        font-size: 30px;
        color: red;
    }
</style>

组件引用结构-----在App.vue当中设置如下属性:

html 复制代码
<script>
   //第一步引入组件
   import MyApp  from './components/MyApp.vue';

   export default{
        //第二步:注册组件
        components:{
            MyApp
        }
   }
</script>
<template>
    <!--第三步:显示组件-->
    <MyApp/>
</template>

二、组件的嵌套关系

组件允许我们将UI划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构

这和我们嵌套HTML元素的方式类似,Vue实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。

新建pages文件夹,并创建以下文件'

1. 基础架构

Header.vue

html 复制代码
<template>
    <h3>Header</h3>
</template>
<style scoped>
    h3{
        width: 100%;
        height: 120px;
        border: 4px solid #333;
        text-align: center;
        line-height: 100px;
        box-sizing: border-box;
    }
</style>

在App.vue当中注册

html 复制代码
<script>
  import Header from './components/Header.vue';
  export default{
    data(){

    },
    components:{
      Header
    }
  }
</script>
<template>
  <Header/>
</template>

Main.vue:

html 复制代码
<template>
    <div class="main">
        <h4>Main</h4>
    </div>
    
</template>

<style scoped>
    .main{
        float: left;
        width: 60%;
        height: 400px;
        border: 4px solid #333;
        text-align: center;
        line-height: 100px;
        box-sizing: border-box;
    }
    .main h4{
        text-align: center;
        background-color: beige;
    }
</style>

Aside.vue:

html 复制代码
<template>
    <div class="aside">
        <h4>Aside</h4>
    </div>
    
</template>

<style scoped> 
    .aside{
        float: right;
        width: 30%;
        height: 400px;
        border: 4px solid #333;
        text-align: center;
        line-height: 100px;
        box-sizing: border-box;
    }
</style>

2. 嵌套

新建Article.vue:

html 复制代码
<template>
    <h5>Article</h5>
</template>
<style>
    h5{
        width:80%;
        margin:0 auto;
        text-align: center;
        line-height: 50px;
        box-sizing: border-box;
        margin-top: 20px;
        background:#999;
    }
</style>

main.vue里引用article.vue

html 复制代码
<template>
    <div class="main">
        <h4>Main</h4>
        <Article/>
        <Article/>
    </div>
    
</template>
<script>
    import Article from './Article.vue';
    export default{
        components:{
            Article
        }
    }
</script>
<style scoped>
    .main{
        float: left;
        width: 60%;
        height: 400px;
        border: 4px solid #333;
        text-align: center;
        line-height: 100px;
        box-sizing: border-box;
    }
    .main h4{
        text-align: center;
        background-color: beige;
    }
</style>

新建item.vue:

html 复制代码
<template>
    <h5>Item</h5>
</template>
<style scoped>
    h5{
        width:80%;
        margin: 0 auto;
        text-align: center;
        line-height: 100px;
        box-sizing: border-box;
        margin-top: 10px;
        background:#999;
    }   
</style>

aside.vue里引用item.vue:

html 复制代码
<template>
    <div class="aside">
        <h4>Aside</h4>
        <Item/>
        <Item/>
    </div>
    
</template>
<script>
    import Item from './Item.vue';
    export default{
        components:{
            Item
        }
    }
</script>
<style scoped> 
    .aside{
        float: right;
        width: 30%;
        height: 400px;
        border: 4px solid #333;
        text-align: center;
        line-height: 100px;
        box-sizing: border-box;
    }
</style>

最终效果:


三、组件注册方式

一个Vue组件在使用前需要先被"注册",这样Vue才能在渲染模板时找到其对应的实现。组件注册有两种方式:全局注册和局部注册

1. 局部注册

前边讲的方案就是局部注册

2. 全局注册

我们这里使用Header.vue来进行全局注册,

:那么首先在App.vue当中取消局部注册。

:在main.js当中设置全局注册方式

:最终在哪里需要就在哪里引入

全局注册虽然很方便,但有以下几个问题

1.全局注册,但并没有被使用的组件无法在生产打包时被自动移除(也叫"tree-shaking")。如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的JS文件中

2.全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性

局部注册需要使用components选项。


四、组件传递数据

组件与组件之间不是完全独立的,而是有交集的,那就是组件与组件之间是可以传递数据的传递数据的解决方案就是props

1. 基础架构

首先我们新建一个Parent.vue

html 复制代码
<template>
    <h3>Parent</h3>
</template>
<script>
    export default{
        data(){
            return{
            }
        } 
    }
</script>

其次我们再新建Child.vue

html 复制代码
<template>
    <h3>Child</h3>
</template>
<script>
    export default{
        data(){
            return{
            }
        }
    }
</script>

我们让Parent.vue给Child.vue传值,不过在此之前我们先让Parent成为Child的父组件。

2. 传递多值

也可以传递多个值

3. 动态传递数据

注意事项:

props 传递数据,只能从父级传递到子级,不能反其道而行


五、组件传递多种数据类型

通过props传递数据,不仅可以传递字符串类型的数据,还可以是其他类型,例如:数字、对象、数组等。但实际上任何类型的值都可以作为props的值被传递。

1. Number

parent.vue:

html 复制代码
<template>
    <h3>Parent</h3>
    <Child :title="message" :age="age"></Child>
</template>
<script>
    import Child from './Child.vue'
    export default{
        data(){
            return{
                message:"我是动态的数据!!!",
                age:20
            }
        },
        components:{
            Child
        }
    }
</script>

Child.vue:

html 复制代码
<template>
    <h3>Child</h3>
    <p>{{ title }}</p>
    <p>{{ age }}</p>
</template>
<script>
    export default{
        data(){
            return{

            }
        },
        props:["title","age"]
    }
</script>

2. Array

parent.vue:

html 复制代码
<template>
    <h3>Parent</h3>
    <Child :title="message" :age="age" :names="names"></Child>
</template>
<script>
    import Child from './Child.vue'
    export default{
        data(){
            return{
                message:"我是动态的数据!!!",
                age:20,
                names:["张三","李四","王五"]
            }
        },
        components:{
            Child
        }
    }
</script>

child.vue:

html 复制代码
<template>
    <h3>Child</h3>
    <p>{{ title }}</p>
    <p>{{ age }}</p>
    <ul>
        <li v-for="(item,index) of names" :key="index">{{ item }}</li>
    </ul>
</template>
<script>
    export default{
        data(){
            return{

            }
        },
        props:["title","age","names"]
    }
</script>

3. Object

parent.vue:

html 复制代码
<template>
    <h3>Parent</h3>
    <Child :title="message" :age="age" :names="names" :userInfo="userInfo"></Child>
</template>
<script>
    import Child from './Child.vue'
    export default{
        data(){
            return{
                message:"我是动态的数据!!!",
                age:20,
                names:["张三","李四","王五"],
                userInfo:{
                    name:"admin",
                    age:20
                }
            }
        },
        components:{
            Child
        }
    }
</script>

child.vue:

html 复制代码
<template>
    <h3>Child</h3>
    <p>{{ title }}</p>
    <p>{{ age }}</p>
    <ul>
        <li v-for="(item,index) of names" :key="index">{{ item }}</li>
    </ul>
    <p>{{ userInfo.name }}</p>
    <p>{{ userInfo.age }}</p>
</template>
<script>
    export default{
        data(){
            return{

            }
        },
        props:["title","age","names","userInfo"]
    }
</script>

六、组件传递Props的校验

Vue组件可以更细致地声明对传入的props的校验要求。

以下例子为接收 String 类型传输 number 控制台警告:

html 复制代码
<script>
import ComponentB from './ComponentB.vue';
export default{
    data(){
    return{
      title:20
    }
  },
    components:{
      ComponentB
    }
}
</script>
<style>
</style>
<template>
    <h3>ComponentA</h3>
    <ComponentB :title="title"/>
  </template>
html 复制代码
<template>
    <h3>ComponentB</h3>
    <p>{{ title }}</p>
</template>
<script>
export default{
    data(){
        return{
           
        }
    },
    props:{
        title:{
            type:String
        }
    }
}
</script>

可以接收多种类型

html 复制代码
props:{
   title:{
       type:[String,Number,Array,Object]
   }
}

1. 默认值

模拟情况:传递数据的时候并没有真实传递。

数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值。

html 复制代码
<template>
    <h3>ComponentA</h3>
    <ComponentB :title="title" :age="age" :names="names"/>
</template>

<script>

import ComponentB from './ComponentB.vue';

export default{
    data(){
        return{
            title:"测试",
            //age:20,
            //names:["Tom","Bob"]
        }
    },
    components:{
        ComponentB
    }
}
</script>
________________________________________________________________________________
<template>
    <h3>ComponentB</h3>
    <p>{{ title }}</p>
    <p>{{ age }}</p>
    <ul>
        <li v-for="(name,index) of names" :key="index">{{ name }}</li>
    </ul>
</template>

<script>
export default{
    data(){
        return{

        }
    },
    props:{
        title:{
            type:[String,Number,Array,Object]
        },
        age:{
            type:Number,
            default:0
        },
        //数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值
        names:{
            type:Array,
            default(){
                return ["xxx"]
            }
        }
    }
}
</script>

2. 必选项

没有传值就会提示警告。

html 复制代码
<template>
  <h3>ComponentA</h3>
  <ComponentB :title="title" :age="age" :names="names"/>
</template>

<script>

import ComponentB from './ComponentB.vue';

export default{
  data(){
      return{
          // title:"测试",
          age:20,
          names:["Tom","Bob"]
      }
  },
  components:{
      ComponentB
  }
}
</script>
html 复制代码
<template>
    <h3>ComponentB</h3>
    <p>{{ title }}</p>
    <p>{{ age }}</p>
    <ul>
        <li v-for="(name,index) of names" :key="index">{{ name }}</li>
    </ul>
</template>

<script>
export default{
    data(){
        return{

        }
    },
    props:{
        title:{
            type:[String,Number,Array,Object],
            required:true
        },
        age:{
            type:Number,
            default:0
        },
        //数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值
        names:{
            type:Array,
            default(){
                return ["xxx"]
            }
        }
    }
}
</script>

注意:

props 是只读的,不允许修改父元素传递过来的数据。

html 复制代码
<template>
    <h3>ComponentB</h3>
    <p>{{ title }}</p>
    <p>{{ age }}</p>
    <ul>
        <li v-for="(name,index) of names" :key="index">{{ name }}</li>
    </ul>
    <button @click="update">update</button>
</template>

<script>
export default{
    data(){
        return{

        }
    },
    props:{
        title:{
            type:[String,Number,Array,Object],
            required:true
        },
        age:{
            type:Number,
            default:0
        },
        //数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值
        names:{
            type:Array,
            default(){
                return ["xxx"]
            }
        }
    },
    methods:{
        update(){
            console.log(this.title);
            this.title="新数据"
        }
    }
}
</script>
相关推荐
z-robot4 分钟前
Nginx 配置代理
前端
用户479492835691512 分钟前
Safari 中文输入法的诡异 Bug:为什么输入 @ 会变成 @@? ## 开头 做 @ 提及功能的时候,测试同学用 Safari 测出了个奇怪的问题
前端·javascript·浏览器
没有故事、有酒23 分钟前
Ajax介绍
前端·ajax·okhttp
朝新_27 分钟前
【SpringMVC】详解用户登录前后端交互流程:AJAX 异步通信与 Session 机制实战
前端·笔记·spring·ajax·交互·javaee
裴嘉靖29 分钟前
Vue 生成 PDF 完整教程
前端·vue.js·pdf
毕设小屋vx ylw28242632 分钟前
Java开发、Java Web应用、前端技术及Vue项目
java·前端·vue.js
冴羽1 小时前
今日苹果 App Store 前端源码泄露,赶紧 fork 一份看看
前端·javascript·typescript
蒜香拿铁1 小时前
Angular【router路由】
前端·javascript·angular.js
时间的情敌2 小时前
Vite 大型项目优化方案
vue.js
brzhang2 小时前
读懂 MiniMax Agent 的设计逻辑,然后我复刻了一个MiniMax Agent
前端·后端·架构