Vue组件(.vue文件)

Vue 组件

组件的构成

一个.vue 文件就是一个组件

组件都是由三部分组成:html 结构(html 结构都是在 template 标签中)、js 逻辑、css 样式

  • 1)template 只能解析一个根标签
  • 2)js 逻辑都是在 script 标签中,必须设置导出,export default {...}
  • 3)css 样式都是在 style 标签中,必须设置 scoped 属性,是样式组件化
<template>
    <div class="first-cp">
         <h1>第一个组件</h1>
    </div>
</template>

<script>
// .vue 文件类似于模块,可以直接相互导入,所以在组件内部要设置导出
export default {

}

</script>

<style scoped>
/ scoped 可以使样式组件化,只在自己内部起作用 /

</style>

 根组件占位渲染页面组件

<!--
1) App.vue 是项目的根组件,是唯一由 main.js 加载渲染的组件,就是替换 index 页面中的 <div id="app"></div> 的占位标签
2) 实际开发中 App.vue 文件中,只需要书写下方五行代码即可(可以在此基础上额外增加其他代码)
3)router-view 是前台路由占位标签,由 router 插件控制,可以在 router 的配置文件中进行配置
4) router-view 就是根据 router 在 index.js 中配置的路由关系,完成指定路径匹配指定页面组件,进行渲染
5) router-view 会被不同的页面组件替换,就形成了页面跳转
-->

<template>
<div id="app">
<!-- 前台路由占位标签,末尾的 / 代表单标签的结束 -->
<router-view />
</div>
</template>

组件数据局部化处理

"""
1)不管是页面组件还是小组件,都可能会被多次复用
2)复用组件,其实就是复用组件的 页面结构、页面样式、页面逻辑
3)但是页面上的数据需要区分(被复用的两个组件数据多少是有区别的),所以组件的数据要做局部化处理
4)借助函数可以产生局部作用域的特点,为每一次复用组件产生一个独立的作用域
语法:
data () {
    return {// 数据们}
}
"""

案例:

子组件

<template>
    <div class="beat" @click="count += 1">
        {{count}} 下
    </div>
</template>

<script>
export
default {
name:
"Beat",
// 不管是页面组件还是小组件,都可能被复用,页面结构与样式都可以采用一套,但是数据一定要相互独立
data () {
return {
count:
0
}
}
}
</script>

<style scoped>
.beat
{
width
: 100px;
height
: 100px;
background-color
: orange;
text-align
: center;
line-height
: 100px;
border-radius
: 50%;
}
</style>

父组件

<template>
    <div class="home">
        <Beat/>
        <Beat/>
    </div>
</template>
<script>
    import Beat from '@/components/Beat'
    export default {
        components: {Beat,}
    }
</script>

父组件传递数据给子组件

"""
一、组件传参 - 父传子
1)在子组件内部通过 props 设置组件的自定义属性
    props: ['abc', 'goods']
2)在父组件中渲染子组件是对自定义属性赋值即可
    <GoodsBox v-for="goods in goods_list" :abc="goods" :goods="goods"/>
"""

子组件:

<template>
    <div class="goods-box">
        <img :src="goods.img" alt="">
        <p>{{goods.title}}</p>
    </div>
</template>

<script>
export
default {
name:
"GoodsBox",
// 在组件内部通过 props 定义组件的自定义属性
props: ['abc', 'goods'],
}
</script>

<style scoped>
.goods-box
{
width
: 260px;
height
: 300px;
border
: 1px solid black;
border-radius
: 5px;
margin
: 20px;
float
: left;
overflow
: hidden;
text-align
: center;
}
img
{
width
: 260px;
height
: 260px;
}
</style>

父组件:

<template>
    <div class="goods">
        <div class="main">
            <!-- 在使用子组件是对自定义属性赋值即可 -->
            <GoodsBox v-for="goods in goods_list" :abc="goods" :goods="goods" />
        </div>
    </div>
</template>
<script>
    import GoodsBox from "../components/GoodsBox";
let goods_list </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">=</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> [
    {
        img: require(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">@/assets/img/001.jpg</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">),
        title: </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">小猫</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">,
    },
    {
        img: require(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">@/assets/img/004.jpg</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">),
        title: </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">小狗</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">,
    },
];

export </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">default</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> {
    name: </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">"</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">Goods</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">"</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">,
    data () {
        </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">return</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> {
            goods_list,
        }
    },
    components: {
        GoodsBox,
    },
}

</script>

子组件传递数据给父组件

"""
二、组件传参 - 子传父
前提:子组件是被父组件渲染的,所以子组件渲染要晚于父组件
1)子组件一定要满足一个条件,才能对父组件进行传参(某个时间节点 === 某个被激活的方法)
    eg:i)子组件刚刚加载成功,给父组件传参 ii)子组件某一个按钮被点击的时刻,给父组件传参 iii)子组件要被销毁了,给父组件传参

2)在子组件满足条件激活子组件的方法中,对父组件发出一个通知,并将数据携带处理(自定义组件事件)
<div class="goods-box" @click="boxClick"></div>
methods: {
boxClick (){ this.$emit('receiveData', this.goods.title, '第二个数据', '第三个数据') }
}

3)在父组件渲染子组件时,为自定义事件绑定方法
<GoodsBox @receiveData="recFn"/>

4)在父组件实现绑定方法时,就可以拿到子组件传参的内容(接收到了通知并在父组件中相应)
methods:{
recFn(title,data2,data3){
console.log('接收到了'+title);
this.goodsTitle = title
}

注意:组件标签不能绑定系统定义的事件,没有意义,子组件的事件都是在自己内部完成
"""

子组件

<template>
    <div class="goods-box" @click="boxClick">
        <img :src="goods.img" alt="">
        <p>{{goods.title}}</p>
    </div>
</template>

<script>
export
default {
props: [
'abc', 'goods'],
methods: {
boxClick () {
// 通知父级 - 自定义组件的事件 'receiveData',然后把数据 this.goods.title 传给父组件
this.$emit('receiveData', this.goods.title)
}
}
}
</script>

父组件

<template>
    <div class="goods">
        <div class="main">
            <!-- 实现自定义事件,接收子组件通知的参数 -->
            <GoodsBox v-for="goods in goods_list" @receiveData="recFn"/>
        </div>
    </div>
</template>
<script>
    import GoodsBox from "../components/GoodsBox";
    export default {
        name: "Goods",
        data () {
            return {
                goodsTitle: '哪个',
            }
        },
        methods: {recFn(title) {
                console.log('接收到了' + title);
                this.goodsTitle = title;
            }
        },
        components: {GoodsBox,},
    }
</script>

组件的生命周期钩子

"""
一、组件的生命周期:一个组件从创建到销毁的整个过程
二、生命周期钩子:在一个组件生命周期中,会有很多特殊的时间节点,且往往会在特定的时间节点完成一定的逻辑,特殊的时间节点可以绑定钩子
注:钩子 - 提前为某个事件绑定方法,当满足这个事件激活条件时,方法就会被调用 | 满足特定条件被回调的绑定方法就称之为钩子
"""
<template>
    <div class="goods">
        <Nav />
    </div>
</template>
<script>
    import Nav from "../components/Nav";
    export default {
        name: "Goods",
        components: {Nav,},
        beforeCreate() {
            console.log('该组件要被加载了') },
        created() { // 重要:请求后台数据,将请求的结果保存在前台页面
            console.log('该组件被加载成功了') },
        updated() { // 以及 beforeUpdate 钩子,监听着页面中的所有数据
            console.log('数据更新了') },
        destroyed() {
            console.log('该组件销毁了')}}
</script>