vue学习笔记-03

目录

一、组件基础

二、组件交互

1、props组件交互

先来解释第一种接收形式:数组形式:

 props接收对象形式:

2、自定义事件交互

 三、组件的生命周期

 四、动态组件

 五、缓存组件

 六、异步组件


一、组件基础

1、vue是组件化开发,将整体拆分成很多的小模块

2、vue单文件组件(又名xx.vue 文件,缩写sfc)是一种特殊的文件格式

它允许将vue组件的模版(html vue叫template),逻辑(js)与样式(css)封装在单个文件中

3、要使用组件,就要知道组件注册的步骤:

  • 第一步:引入组件
  • 第二步:挂载组件(通过components进行挂载)
  • 第三步:显示组件

文件结构:

代码演示:

 在App.vue根组件中

<template>
  <div id="app">
    <!-- 第三步:使用组件 -->
    <MyCompoent/>
  </div>
</template>

<script>
// 第一步:引入组件
import MyCompoent from './components/MyCompoent.vue';
export default {
  components: {
    // 第二步:注册组件
    MyCompoent
  }
}
</script>

在MyCompoent.vue中

scoped: 如果在style中添加此属性,就代表着只在当前样式只在当前组件中生效

<template>
    <div>
        <h1>我是MyCompoent组件</h1>
    </div>
</template>

<style lang="less" scoped>
h1 {
    color: skyblue;
}
</style>

 效果展示:

二、组件交互

组件和组件之间是存在数据交互的。组件和组件的交互有props自定义事件两种方式。

1、props组件交互

props是将父组件的数据传入子组件

文件结构:

 先在app.vue注册使用PropFather.vue组件

在父组件Father.vue中使用子组件Son.vue

 父向子传值:可以传静态数据,也可以传动态数据

这样我们就向子组件传入了静态的msg和动态的msg1

<template>
    <div>
        <h1>我是父组件</h1>
        <hr>
        <Son msg="我是父组件的静态数据msg" :msg1="msg1"/>
    </div>
</template>

<script>
import Son from './Son.vue'
export default {
    components: {
        Son
    },
    data() {
        return {
            msg1: "我是父组件的动态数据msg1"
        }
    }
}
</script>

这里只是传给了子组件并不能看到效果,得要子组件接收并展示。

对于props的接收形式有两种:一是数组形式,二是对象的形式

子组件props接收到的值不用在data中声明,可以直接使用。

先来解释第一种接收形式:数组形式:

<template>
    <div>
        <h2>我是子组件</h2>
        <p>{{  msg  }}---{{  msg1  }}</p>
    </div>
</template>

<script>
export default {
    // 第一种:数组形式
    props: ['msg','msg1']
}
</script>

<style lang="less" scoped>

</style>

内容展示:

 props接收对象形式:

传入的对象要进行类型校验

<template>
    <div>
        <h2>我是子组件</h2>
        <p>{{  msg  }}---{{  msg1  }}</p>
    </div>
</template>

<script>
export default {
    props: {
        msg: String,
        msg1: String
    }
}
</script>

上面是传入对象的最简单的写法。

下面是所有传入对象的其他写法:

props: {
    // 基础的类型检查(null 和 undefined 会通过任何类型验证) 
    valueA: Number,
    // 多个可能的类型
    valueB: [String, Number],
    // 必填的字符串(必传)
    valueC: {
        type: String,
        required: true
    },
    // 带有默认值的数字
    valueD: {
        type: Number,
        default: 100
    },
    // 自定义验证函数
    valueF: {
        validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
        }
    }
}

这里要注意一点:如果类型是数组和对象默认值必须使用函数(工厂模式)进行返回

props: {
    arr: {
        type: Array,
        // 数组和对象默认值必须使用函数(工厂模式)进行返回
        // 错误写法: default: []
        default: function () {
            // 返回为空
            return []
        }
    }
}

2、自定义事件交互

上面讲了props可以将数据从父组件传递到子组件, 那么自定义事件可以在组件中反向传递数据。从子组件传递数据到父组件就可以使用自定义事件实现 $emit

在子组件中,要通过事件进行触发,通过this.$emit(参数1,参数2)来注册自定义事件。

参数1: 字符串,也就是自定义事件的名字,在父组件当作事件来使用

参数2: 传递的数据

通过代码来更清楚的了解:

<template>
    <div>
        <h2>我是子组件</h2>
        <button @click="sendClickHandle">点击传递</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            message: "我是Son数据"
        }
    },
    methods: {
        sendClickHandle() {
            this.$emit("onEvent", this.message)
            // 将 onEvent 在父组件当作事件来处理
        }
    }
}
</script>

通过子组件注册的自定义事件名“onEvent”,接下来在父组件中进行使用:

<template>
    <div>
        <h1>我是父组件</h1>
        <p>{{msg}}</p>
        <!-- 这里的onEvent就是通过子组件注册的事件名 -->
        <Son @onEvent="getDateHandle" />
    </div>
</template>

<script>
import Son from './Son.vue'
export default {
    components: {
        Son
    },
    // data用来接收数据
    data() {
        return {
            msg: ""
        }
    },
    methods: {
        getDateHandle(data) {
            this.msg = data;
        }
    }
}
</script>

因为子组件的this.message数据给到了自定义事件的参数里,所以父组件自定义事件中的getDateHandle 可以拿到数据data。把传递来的参数赋值给msg就能显示出来。

通过点击子组件的button,父组件就获取到了数据了。

 三、组件的生命周期

组件的生命周期: vue组件从创建到销毁的过程

钩子函数(生命周期函数): 在特定时间点上触发的函数,不需要我们自己调用。组件加载到某个阶段后,会自动触发。用它就是把一些特定的逻辑放在指定的钩子函数里。

vue2中有8个生命周期函数(vue2和vue3有些差别)

创建时: beforeCreate, created

渲染时: beforeMount, mounted

更新时: beforeUpdate, updated

卸载时: beforeDestroy, destroyed

 下面根据代码可以更直观的了解:

<template>
    <div>
        <h2 ref="myname">小天</h2>
        <button @click="btnDestroy">销毁</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            msg: '123'
        }
    },
    methods: {
        btnDestroy() {
            this.$destroy(); // 对组件进行销毁
        }
    },
    // 创建之前,特点:数据代理还未完成,访问不到数据和方法,但是可以this VUe实例
    beforeCreate() {
        console.group('beforeCreate: 数据代理还没有完成,访问不到数据和方法')
        console.log(this);  // Vue实例
        console.log('$el:', this.$el);  // $el是dom元素
        console.log('msg:', this.msg);
    },
    created() {
        console.group('created: 数据代理已经完成,能访问数据和方法。最早可以发送网络请求的地方')
        console.log('$el:', this.$el);
        console.log('msg:', this.msg);
    },
    beforeMount() {
        // 和mounted的html有不同
        console.group('beforeMount: 挂载之前')
        console.log('$el:', this.$el);
        console.log('msg:', this.msg);
    },
    mounted() {
        console.group('mounted: 挂载完成, 页面进入稳定运行状态。获取dom元素, 开启定时器, 绑定事件监听')
        console.log('$el:', this.$el);
        console.log('msg:', this.msg);
    },
    // 下面的需要特定条件触发才显示
    beforeUpdate() {
        // 数据更新之后,界面更新之前触发的钩子函数
        console.group('beforeUpdate: 数据已经更新,界面更新之前触发')
        console.log(this.flag, this.$refs.myname.innerHTML);
    },
    updated() {
        console.group('updated: 数据已经更新,界面也已经更新完成')
        console.log(this.flag, this.$refs.myname.innerHTML);
    },
    beforeDestroy() {
        // 销毁之前 例如销毁定时器
        console.group('beforeDestroy: 销毁之前,做一些收尾工作,例如销毁定时器')
    },
    destroyed() {
        console.group('销毁之后')
    }
}
</script>

上面提到的this是vue实例,$el是dom元素。

 四、动态组件

动态加载,可以用来写tab选项卡

用法:<component :is="组件名"></component> 只有写了组件才会展示出来

使用时,还是必须对组件进行引入和注册,但是挂载变成了动态的,通过<component :is="xxx"></component>动态挂载

<template>
  <div id="app">
    // 3、动态创建
    <component :is="'one'"></component>
    <component :is="'two'"></component>
  </div>
</template>

<script>
// 1、对组件进行引入
import one from './components/one.vue';
import two from './components/two.vue';
export default {
  name: 'App',
  // 2、注册组件
  components: {
    one,
    two
  }
}
</script>

 五、缓存组件

之前的动态组件,每次切换一次 mounted 执行一次,说明每次切换渲染一次。当组件比较多,内容较多的话,耗性能。

用法:keep-alive包住component

<keep-alive :exclude="['组件名1']">

        <component :is="组件名"></component>

</keep-alive>

这里的 :exclude="['组件名1']"也可以没有

exclude:字符串或正则表达式。任何名称匹配的组件都不会被缓存。

include:字符串或正则表达式。只有名称匹配的组件会被缓存。

使用和动态组件是差不多的,只是外面包裹了一层。

这里重点注意的是:

  • 缓存组件被缓存了, mounted只会执行一次, beforeDestroy不会被卸载有两个生命周期来代替 mounted 和 beforeDestroy。
  • 当使用keep-alive可使用 activated 来代替 mounted 发送请求。
  • 当使用keep-alive可使用 deactivated 来代替 destoyed 收尾工作, 比如清除缓存数据。
  • 缓存后就不走挂载和卸载

 根据下面的例子来深入了解:

在App.vue中

<template>
  <div id="app">
    <!-- 动态组件 -->
    <div class="tabs">
      <div class="tab-item" @click="changeTab('Home')">Home</div>
      <div class="tab-item" @click="changeTab('Personal')">Personal</div>
    </div>
    <component :is="comName"></component>
    <hr>
    <!-- 缓存组件 -->
    <div class="tabs">
      <div class="tab-item" @click="keepChange('KeepHome')">Home</div>
      <div class="tab-item" @click="keepChange('KeepPersonal')">Personal</div>
    </div>
    <keep-alive>
      <component :is="keepComName"></component>
    </keep-alive>
  </div>
</template>

<script>
import Home from './components/01-dynamicComponent/Home.vue';
import Personal from './components/01-dynamicComponent/Personal.vue';
import KeepHome from './components/02-keepComponent/KeepHome.vue';
import KeepPersonal from './components/02-keepComponent/KeepPersonal.vue';

export default {
  name: 'App',
  components: {
    Home,
    Personal,
    KeepHome,
    KeepPersonal
  },
  data() {
    return {
        comName: 'Home',
        keepComName: 'KeepHome'
    }
  },
  methods: {
    changeTab(name) {
      this.comName = name;
    },
    keepChange(name) {
      this.keepComName = name;
    }
  }
}
</script>

在动态组件Home.vue中写:

export default {
    name: 'Home',
    mounted() {
        console.log('Home挂载完成');
    },
    beforeDestroy() {
        console.log('Home组件即将卸载');
    }
}

在缓存组件KeepHome.vue中写:

export default {
    name: 'KeepHome',
    // mounted只会使用一次,beforeDestroy不会被执行
    mounted() {
        console.log('keepHome 挂载完成');
    },
    beforeDestroy() {
        console.log('keepHome 组件即将卸载');
    },
    // 代替上面两个:
    activated() {
        console.log('keepHome 处于激活状态');
    },
    deactivated() {
        console.log('keepHome 处于失活状态');
    }
}

缓存组件的mounted只有当页面第一次加载的时候执行一次,而beforeDestroy不会被执行。

组件的加载和卸载变成了激活和失活状态。

刚进页面时:

 对动态组件的tab进行切换,会不断打印出挂载和卸载:

但是对缓存组件进行切换,就变成了失活和激活,不会走挂载和卸载:

 六、异步组件

在大型应用中,我们可能需要将应用分割成小一些的代码,并且只在需要的时候才从服务器加载一个模块。vue只有在这个组件需要被渲染的时候才会触发该工厂函数,并且会把结果缓存起来供未来重渲染。

简而言之,异步组件就是:使用时再加载。

import MyComponent from './component/MyComponent.vue'  这种写法是同步写法

异步组件导入:用箭头函数加import

示例代码:

写法一:

<template>
  <div id="app">
    <!-- 使用组件 -->
    <Async/>
  </div>
</template>

<script>
// 1、异步引入
const Async = () => import('./components/Async.vue')
export default {
  name: 'App',
  // 2、注册组件
  components: {
    Async
  }
}
</script>

写法二:将引入和注册合成一步了

<template>
  <div id="app">
    // 使用
    <Async/>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {
    // 1、2 引入和注册
    Async: () => import('./components/Async.vue')
  }
}
</script>

关于组件的内容暂时就这么多了吧🌝

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值