百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

vue3学习11、12、13组件化开发(vue组件化开发案例)

ztj100 2024-11-12 14:22 33 浏览 0 评论

利用vue脚手架创建一个项目

vue create component_demo

可以在vscode中安装Vue VSCode Snippets插件或vue3 snippets,帮助生成一些代码片段

vbase-css

可以快速生成vue3模板

组件通信

父子组件之间通信

  • 父组件传递给子组件:通过props属性
  • 子组件传递给父组件:通过$emit触发事件

在父组件中引入组件传值

<show-message :title="title"></show-message>

子组件中在props中定义

    props: {
      title: {
        type: String,
        require: true,   //表示这个属性是必传的
        default: '123'  //默认属性
      },
      //当属性是Object型时,默认值要为一个函数.因为多个组件会引用同一个对象
      info: {
        type: Object,
        default() {
          return {name: 'juju'}
        }
      },
      //自定义验证函数
      man: {
        validator(value) {
          //这个值必须匹配下列字符串中的一个
          return ['success', 'warning', 'danger'].include(value)
        }
      }
    }

props命名 建议父组件中要传递的值采用驼峰写法

<show-message :message-info="title"></show-message>
...


data() {
    return {
        messageInfo: 'damn'
    }
}

非props的Attribute

当我们传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits,就称之为非props的Aaaribute

常见的包括css,style,id属性等 例如当给子组件设置一个class属性

<show-message class="liin" :title="title"></show-message>

当组件有单个根节点时,会自动添加到根节点的attribute

<template>
  <div class="liin">
    <h2>{{ title }}</h2>
    <h2>{{ info.name }}</h2>
  </div>
</template>

如果我们不希望根组件继承attribute,可以在子组件中设置inheritAttrs: false 我们可以通过$attrs来访问所有的非props的attribute

<h2 :class="$attrs.class">{{ title }}</h2>

通过v-bind绑定所有属性 父组件

<show-message id="xixi" class="liin" :title="title"></show-message>

子组件

<h2 v-bind="$attrs">{{ title }}</h2>

子组件传递给父组件 子组件中与vue2不同的是多了个emit参数,里面存放着可能要触发的事件

  export default {
    //emits属性,里面存放着待会会触发的事件
    emits: ["add", "sub"],
    //emits的对象写法,目的是为了进行参数的验证
    emits: {
      sub: null,
      add: (name, age) => {
        if(name == 'juju') {
          return true
        }
        return false
      }
    },
    methods: {
      increament() {
        this.$emit("add","juju",18)   //后面多个参数跟着的是要传的参数
      },
      decreament() {
        this.$emit("sub")
      },
    }
  }

父组件中写法与vue2相同

<counter-operation @add="addOne" @sub="subOne"></counter-operation>

非父组件的通信

  • provide/inject
  • mitt全局事件总线
  • vuex

provide和inject

无论层级结构有多深,父组件都可以作为其所有子组件的依赖提供者; 父组件有一个provide选项来提供数据,子组件有一个inject选项来使用这些数据

在父组件中添加一个provide

    components: {
      Home
    },
    provide: {
      name: 'juju',
      age: 18
    },

在子孙组件中注入

  export default {
    inject: ["name", "age"]
  }

当然,许多情况下数据都要从data中拿并从后台请求了,此时的provide要写成函数形式

    provide() {
      return {
        name: juju,
        age: 18,
        title: this.title
      }
    },

如果后续title改变的话,inject里的值并不是响应式的,可以使用vue中的computed函数


import {computed} from 'vue'

    provide() {
      return {
        name: juju,
        age: 18,
        title: computed(() => {
          this.title
        })
      }
    },

全局事件总线mitt库

安装mitt库

npm install mitt

创建一个eventbus.js文件

import mitt from 'mitt'

const emitter = mitt();

export default emitter;

// 也可以创建多个mitt对象

测试叔侄组件之间通信 在叔组件中传递

import emmiter from '../util/eventbus.js'

    methods: {
      btnClick() {
        emmiter.emit("handle", "juju",18);  //第一个参数方法名,后面跟着的是参数
      }
    }

在侄组件的生命周期中监听

    import emitter from '../util/eventbus.js'
    created() {
      emitter.on("handle", (name,age)=> {
        console.log(name)
      })
    }

mitt事件取消

emitter.all.clear();  //全部取消监听

function onFoo(){}
emitter.on('foo', onFoo)  //监听
emitter.off('foo', onFoo)  //取消监听

插槽slot

对于不同的区域可能存放不同的内容,因此要使用slot

  • 插槽的使用过程其实是抽取共性,预留不同
  • 我们会将共同的元素,内容依然在组件内进行封装
  • 同时将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素

简单插槽的使用

定义一个子组件

    <h2>组件开始</h2>
    <slot></slot>
    
    <h2>组件结束</h2>

在父组件中使用

    <my-slot-cpn>
      <button>我是按钮</button>
    </my-slot-cpn>

此时中间部分可以展示按钮或者图片或者组件,vue会将内容替换到slot的位置

具名插槽的使用

插槽的默认使用 如果子组件是这样的

  <div>
    <h2>组件开始</h2>
    <slot>
      <i>我是默认内容</i>
    </slot>

    <h2>组件结束</h2>
  </div>

父组件

    <my-slot-cpn>
    </my-slot-cpn>

则显示默认内容

具名插槽

在子组件中编写有name属性的插槽

<template>
  <div class="nav-bar">
    <div class="left">
      <slot name="left"></slot>
    </div>
    <div class="center">
      <slot name="center"></slot>
    </div>
    <div class="right">
      <slot name="right"></slot>
    </div>
  </div>
</template>

在父组件中用template v-slot方式分配元素至对于的slot内

    <!-- 具名插槽的使用 -->
    <nar-bar>
      <template v-slot:left>
        <button>左边按钮</button>
      </template>
      //等价于
       <template #left>
        <button>左边按钮</button>
      </template>
      <template v-slot:center>
        <h2>我是标题</h2>
      </template>
      <template v-slot:right>
        <i>右边的元素</i>
      </template>
    </nar-bar>

效果

如果名字是不定的话,template应该这么写

      <template v-slot:[name]>
        <i>右边的元素</i>
      </template>

作用域插槽

即子组件中的slot属性,可以传给父组件 子组件

<template>
  <div>
    <template v-for="(item,index) in names" :key="item">
      <slot :item="item" :index="index"></slot>
    </template>
  </div>
</template>

父组件通过v-slot取得

  <show-names>
    <template v-slot="slotProps">
      <button>{{slotProps.item}}-{{ slotProps.index }}</button>
    </template>
  </show-names>
  //是下面的简写,v-slot后跟插槽名字
    <show-names>
    <template v-slot:default="slotProps">
      <button>{{slotProps.item}}-{{ slotProps.index }}</button>
    </template>
  </show-names>

当只有默认插槽时,可以使用独占默认插槽写法

    <show-names v-slot="slotProps">
      <button>{{slotProps.item}}-{{ slotProps.index }}</button>
  </show-names>

动态组件的实现

根据不同的场景,去渲染不同的组件。以前基本都使用v-if去判断从而渲染不同的组件。但是当组件很多的时候,组件会显得很臃肿。此时可以考虑采用动态组件去实现。

动态组件是使用component组件,通过特殊的attribute is来实现。 例如

<component is="hello-world"></component>

此时就会渲染HelloWorld组件

动态组件传递参数

<component is="hello-world" name="juju" :age="18" @helloClick="handleClick"></component>

此时在helloworld组件可以用props接收,同时动态组件可以接受子组件的点击事件

keep-alive

默认情况下,切换组件会被销毁,再次回来会重新创建组件。此时,在开发中某些情况我们希望继续保持组件的状态,而不是销毁掉,这时我们可以使用一个内置组件:keep-alive。

<keep-alive>
    <component is="hello-world" name="juju" :age="18" @helloClick="handleClick"></component>
<keep-alive>

keep-alive有一些属性,

  • include.[string|regexp|array]只有名称匹配的组件会被缓存。
  • exclude[string|regexp|array]任何匹配的组件都不会会被缓存。
  • max[number|string]最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁


include是根据组件的name属性来进行适配,因此有时需要给组件加上name属性

  export default {
    name: 'about',
   }

webpack分包

正常打包的话会将所有资源打包到一个app.js文件中,采用webpack分包方式会将利用分包的资源打包到一个chunk文件中,需要时再去加载,可以优化首屏渲染。

//通过import函数导如的模块,后续webpack对其进行打包的时候就会进行分包的操作
import('./utils/math').then(res => {console.log(sum(10,20))})

异步组件

同时vue3提供一个函数可以使打包后的组件成为一个单独的文件夹,加快首屏渲染速度 defineAsyncComponent接受两种类型的参数: 类型一:工厂函数,该工厂函数需要返回一个promise对象 类型二:接受一个对象类型,对异步函数进行配置

import {defineAsyncComponent} from 'vue'
const AsyncHello = defineAsyncComponent(() => import('./components/HelloWorld.vue'))

一般开发中使用路由懒加载比较多

获取元素和refs

在某些情况下,我们组件想要直接获取到元素对象或者子组件实例 在vue开发中我们不推荐dom操作的,这个时候,可以给元素或者组件绑定以恶搞ref的attribute属性

<h2 ref="title">哈哈哈哈哈哈</h2>


    mounted() {
      console.log(this.$refs.title)
    },

打印结果


对于组件来说,调用this.refs.xx可以获取组件实例,取得data中的数据或调用一些方法。 同时,可以在子组件中采用this.parent取得父组件实例以及parent取得父组件实例以及parent取得父组件实例以及root获取根组件

组件的生命周期

  • beforecreated
  • created
  • beforemounted
  • mounted
  • beforeUpdate
  • updated
  • beforeUnmount
  • unmounted

对于有缓存的组件来说,再次进入时,我们是不会执行created或者mounted等生命周期的,这时我们可以使用activated和deactiveated这两个生命周期钩子函数来监听。

组件的v-model

    //组件绑定v-model与下列的等价
    <hy-input v-model="title"></hy-input>
    <!-- <hy-input :modelValue="title" @update:model-value="title = $event"></hy-input> -->
<template>
  <div>
    <button @click="btnClick">input按钮</button>
    {{ modelValue }}
  </div>
</template>

<script>
  export default {
    props: {
      modelValue: String
    },
    emits: ["update:modelValue"],
    methods: {
      btnClick() {
        this.$emit("update:modelValue", '嘿嘿')
      }
    }
  }
</script>

$event为update:model-value事件传出来的参数

如果子组件中有input可以实现v-model绑定计算属性的操作,因为不能绑定到props里

    <input v-model="value" />
    
    ...
    computed: {
      value: {
        get(){
          return this.modelValue
        },
        set(value) {
          this.$emit("update:modelValue", value)
        }
      }
    },  

绑定多个v-model,后面加名字,此时why为子组件prop的值

<hy-input v-model="title" v-model:why="why"></hy-input>

相关推荐

Vue3非兼容变更——函数式组件(vue 兼容)

在Vue2.X中,函数式组件有两个主要应用场景:作为性能优化,因为它们的初始化速度比有状态组件快得多;返回多个根节点。然而在Vue3.X中,有状态组件的性能已经提高到可以忽略不计的程度。此外,有状态组...

利用vue.js进行组件化开发,一学就会(一)

组件原理/组成组件(Component)扩展HTML元素,封装可重用的代码,核心目标是为了可重用性高,减少重复性的开发。组件预先定义好行为的ViewModel类。代码按照template\styl...

Vue3 新趋势:10 个最强 X 操作!(vue.3)

Vue3为前端开发带来了诸多革新,它不仅提升了性能,还提供了...

总结 Vue3 组件管理 12 种高级写法,灵活使用才能提高效率

SFC单文件组件顾名思义,就是一个.vue文件只写一个组件...

前端流行框架Vue3教程:17. _组件数据传递

_组件数据传递我们之前讲解过了组件之间的数据传递,...

前端流行框架Vue3教程:14. 组件传递Props效验

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

前端流行框架Vue3教程:25. 组件保持存活

25.组件保持存活当使用...

5 个被低估的 Vue3 实战技巧,让你的项目性能提升 300%?

前端圈最近都在卷性能优化和工程化,你还在用老一套的Vue3开发方法?作为摸爬滚打多年的老前端,今天就把私藏的几个Vue3实战技巧分享出来,帮你在开发效率、代码质量和项目性能上实现弯道超车!一、...

绝望!Vue3 组件频繁崩溃?7 个硬核技巧让性能暴涨 400%!

前端的兄弟姐妹们五一假期快乐,谁还没在Vue3项目上栽过跟头?满心欢喜写好的组件,一到实际场景就频频崩溃,页面加载慢得像蜗牛,操作卡顿到让人想砸电脑。用户疯狂吐槽,领导脸色难看,自己改代码改到怀疑...

前端流行框架Vue3教程:15. 组件事件

组件事件在组件的模板表达式中,可以直接使用...

Vue3,看这篇就够了(vue3 从入门到实战)

一、前言最近很多技术网站,讨论的最多的无非就是Vue3了,大多数都是CompositionAPI和基于Proxy的原理分析。但是今天想着跟大家聊聊,Vue3对于一个低代码平台的前端更深层次意味着什么...

前端流行框架Vue3教程:24.动态组件

24.动态组件有些场景会需要在两个组件间来回切换,比如Tab界面...

前端流行框架Vue3教程:12. 组件的注册方式

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

焦虑!Vue3 组件频繁假死?6 个奇招让页面流畅度狂飙 500%!

前端圈的朋友们,谁还没在Vue3项目上踩过性能的坑?满心期待开发出的组件,一到高并发场景就频繁假死,用户反馈页面点不动,产品经理追着问进度,自己调试到心态炸裂!别以为这是个例,不少人在电商大促、数...

前端流行框架Vue3教程:26. 异步组件

根据上节课的代码,我们在切换到B组件的时候,发现并没有网络请求:异步组件:...

取消回复欢迎 发表评论: