Vue组件化开发--公共组件的封装

这篇具有很好参考价值的文章主要介绍了Vue组件化开发--公共组件的封装。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

为什么要封装组件

应用场景

vue自己封装组件(局部、全局) 

Vue组件的三要素

①全局组件

1)方式:

 2)示例:

②局部组件

1)方式:

2)示例:

命名规范:(注意)

脚手架vue-cli中的组件

父传子(props)

通过 $on 传递父组件方法

$parent获取父组件然后使用父组件中的数据(不推荐)

通过$emit传递父组件数据 (推荐) 

refs获取

组件样式修改 样式穿透 

插件使用:slot


为什么要封装组件

用vue开发的项目,都是采用组件化的思想开发的。

一般在搭建项目的时候,会创建一个views目录、一个commen目录和一个feature目录。

  • views目录中放页面级的组件
  • commen中放公共组件(如:head(公共头组件),foot(公共底部组件)等)
  • feature目录内放功能组件(如:swiper(轮播功能组件),tabbar(切换功能组件)、list(上拉加载更多功能组件))

组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性低等问题。

使用组件的好处

  • 组件是可以复用性的
  • 易于维护
  • 有封装性,易于使用
  • 大型项目中降低组件之间重复性
     

应用场景

项目中很多模块经常会复用:侧边导航组件、分页、文件下载、项目中常用的 echarts图表的封装(比如折线图、柱状图等),或者一些后台管理、菜单管理中很多可复用组件,表单之类的。


封装组件需要考虑复用性:

  • 预留插槽slot, 多次调用如果 子组件视图结构不一样那么就要在子组件template预留好插槽(单个插槽、具名插槽,作用域插槽)
  • 考虑到数据传递,定义props 组件接收父组件传递的数据,同时需要注意单向数据流,props不能直接修改,$emit自定义事件,父组件修改
  • 业务逻辑不要在子组件中处理,子组件在不同父组件中调用时,业务处理代码不同,切记不要直接在子组件中处理业务,应该子组件 $emit自定义事件,将数据传递给父组件,父组件处理业务。

vue自己封装组件(局部、全局) 

封闭性:当在组件定义好外部不能修改;

开放性:将动态内容和组件通讯方式进行传递数据保证组件可扩展性;

Vue组件的三要素

1. props参数
2. slot定制插槽
3. event自定义事件

①全局组件

1)方式:

可以在main.js中注册成全局组件。

import Bread from '@/layout/bread';// 引入
Vue.component("Bread",Bread);// 全局注册

 2)示例:

引用全局组件my-header

<body>
  <div id="main1">
    <!-- 正常模板解析的时候,不会将自定义标签解读出来,而是将自己定义组件里的参数解读出来,也就是下面template中的h1标签 -->
    <my-header></my-header>
  </div>
   <div id="main2">
     <!-- 自定义组件具有复用性 -->
    <my-header></my-header>
  </div>
   <div id="main3">
    <my-header></my-header>
  </div>
</body> 

注册全局组件my-header

//全局组件:在任何地方,任何方式,任何地点都可以使用的标签组件
vue.component("my-header", {
    	// h1标签是我们在自定义主键里面写的参数的标签
    	template: '<h1>标题{{msg}}</h1>',
    	data(){
    	   return {msg:100}
    	}
    })
	new Vue({
	  	el: '#main'
	  });
	  new Vue({
	  	el: '#main2'
	  });
	  new Vue({
	  	el: '#main3'
	  });

②局部组件

1)方式:

  • 新建一个vue文件
  • 在需要使用的组件里引入:import UploadIDCard from “./fillInfo/upIDCard”;
  • 注册
components: {
    Position: () => import("@/layout/position"),
    UploadIDCard
},

注册后,UploadIDCard可以当做一个标签使用。(局部组件)。

2)示例:

局部组件:只是在我们规定的范围之内才会生效。

 <body>
    <div id="main">
      <my-header></my-header>
      <my-header></my-header>
    </div>
  </body>
  new Vue({
    	el: '#main',
    	components: {
    		"my-header": {
    		template: '<h1>标题{{vue}}</h1>'
    		}
    	}
    })

命名规范:(注意

  • 当使用 kebab-case(中划线命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如<my-component-name>
  • 当使用 PascalCase (驼峰式命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。 也就是说<my-component-name>和<MyComponentName> 都是可接受的。注意,尽管如此,直接在 DOM(即非字符串的模板) 中使用时只有kebab-case 是有效的。
  • 总结:中划线命名在使用时必须保持命名一致,而驼峰命名在使用时既可以用驼峰也可以用中划线。
//中划线 使用语法: <my-component-name>`
Vue.component('my-component-name', { /* ... */ })
//驼峰  使用语法:<my-component-name> `和` <MyComponentName>`都可以
Vue.component('MyComponentName', { /* ... */ })

脚手架vue-cli中的组件

组件之间的数据传递
我们一般通过脚手架vue-cli开发项目,每个 .vue单文件就是一个组件。在父组件中使用import 导入一个子组件,并在components中注册子组件,子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用$emit方法触发自定义事件传递参数。

父传子(props)

prop 的定义应该尽量详细,至少需要指定其类型

父组件通过属性的形式向子组件传递数据,子组件使用props接收数据,但是通用组件的应用场景比较复杂,对 props 传递的参数应该添加一些验证规则,即:

props: {
    propA: Number,  // 基础类型检测 (`null` 意思是任何类型都可以)
    propB: [String, Number],   // 多种类型
    propC: {  // 必传且是字符串
      type: String,
      required: true
    },
    propD: {   // 数字,有默认值
      type: Number,
      default: 100
    },
    propE: {   // 数组/对象的默认值应当由一个工厂函数返回
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    propF: {   // 自定义验证函数
      validator: function (value) {
        return value > 10
      }
    }
  }

由于存在一个单项数据流的问题,父组件传递给子组件的数据不要直接修改,因为会将父组件中的数据也修改,当这个数据也传入其他组件的时候就会出问题了。vue2.5已经针对 props 做出优化,这个问题已经不存在了 如果一定需要有这样的操作,可以这么写:

let copyData = JSON.parse(JSON.stringify(this.data))

为什么不直接写 let myData = this.data 呢? 因为直接赋值,对于对象和数组而言只是浅拷贝,指向的是同一个内存地址,其中一个改变另一个也会改变。而通过 JSON颠倒转换之后,实现了深拷贝,则可以互不影响。

<!-- 父组件 -->
<template>
    <div>
        <my-child :parentMessage="parentMessage"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: "我是来自父组件的消息"
            }
        }
    }
</script>
<!-- 子组件 -->
<template>
    <div>
        <span>{{ parentMessage }}</span>
    </div>
</template>

<script>
    export default {
        props: {
            parentMessage: {
                type: String,
                default: '默认显示的信息'
                // require: true // 必填
            }
        }
    }
</script>

通过 $on 传递父组件方法

通过$on传递父组件方法是组件通信中常用的方法传递方式。它可以与通过props传递方法达到相同的效果。相比于props传递function,它更加的直观和显示的表现出了调用关系

<!-- 父组件 -->
<template>
    <div>
        <my-child @childEvent="parentMethod"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild,
        },
        data() {
            return {
                parentMessage: '我是来自父组件的消息',
            }
        },
        methods: {
            parentMethod() {
                alert(this.parentMessage)
            }
        }
    }
</script>
<!-- 子组件 -->
<template>
    <div>
        <h3>子组件</h3>
    </div>
</template>

<script>
    export default{
        mounted() {
            this.$emit('childEvent')
        }
    }
</script>

$parent获取父组件然后使用父组件中的数据(不推荐)

准确来说这种方式并不属于数据的传递而是一种主动的查找。父组件并没有主动的传递数据给子组件,而是子组件通过与父组件的关联关系,获取了父组件的数据。
该方法虽然能实现获取父组件中的数据但是不推荐这种方式,因为vue提倡单向数据流,只有父组件交给子组件的数据子组件才有使用的权限,不允许子组件私自获取父组件的数据进行使用。在父与子的关系中子应当是处于一种被动关系

通过$emit传递父组件数据 (推荐) 

子组件向父组件中传递数据

子组件向父组件中传递数据:触发父组件方法,并传递参数data到父组件

与父组件到子组件通讯中的$on配套使用,可以向父组件中触发的方法传递参数供父组件使用

<!-- 父组件 -->
<template>
    <div>
        <my-child @childEvent="parentMethod"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: '我是来自父组件的消息'
            }
        },
        methods: {
            parentMethod({ name, age }) {
                console.log(this.parentMessage, name, age)
            }
        }
    }
</script>
<!-- 子组件 -->
<template>
    <div>
        <h3>子组件</h3>
    </div>
</template>

<script>
    export default {
        mounted() {
            this.$emit('childEvent', { name: 'zhangsan', age:  10 })
        }
    }
</script>

refs获取

可以通过在子组件添加ref属性,然后可以通过ref属性名称获取到子组件的实例。准确来说这种方式和this.$parent
一样并不属于数据的传递而是一种主动的查找

尽量避免使用这种方式。因为在父子组件通信的过程中。父组件是处于高位是拥有控制权,而子组件在多数情况下应该为纯视图组件,只负责视图的展示和自身视图的逻辑操作。对外交互的权利应该由父组件来控制。所以应当由父组件传递视图数据给子组件,子组件负责展示。而子组件的对外交互通过$emit触发父组件中相应的方法,再由父组件处理相应逻辑。

<!-- 父组件 -->
<template>
    <div>
        <my-child ref="child"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        mounted() {
            console.log(this.$refs['child'].getData());
        }
    }
</script>
<!-- 子组件 -->
<script>
    export default {
        methods: {
            getData() {
                // do something...
            }
        }
    }
</script>

组件样式修改 样式穿透 

sass中语法
有些像sass之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/操作符取而代之——这是一个>>>的别名,同样可以正常工作

<style scoped>
    .a /deep/ .b { /* ... */ }
</style>

插件使用:slot

一个通用组件,往往不能够适应所有应用场景,所以在封装组件的时候只需要完成组件 80% 的功能,剩下的 20% 让父组件通过 solt 解决。solt 起到一个占位的作用,给按钮的设置提前预留一个位置,然后在父组件中写入按钮即可。

在开发通用组件的时候,只要不是独立性很强的组件最好是都加一个slot。并且,开发过程中,常常需要在子组件内添加新的内容,这时候可以在子组件内部留一个或者多个插口,然后在调用这个子组件的时候加入内容,添加的内容就会分发到对应的 slot 中:

父组件
<head-component>
	<h2>不具名插槽</h2>
	<h2 slot="s1">这里对应的是s1插口</h2>
	<h2 slot="s2">这里对应的是s2插口</h2>
</head-component>
子组件
<template>
  <div class="headComponent">
    <h3>这是一个头部组件</h3>
    <slot></slot>
    <slot name="s1"></slot>
    <slot name="s2"></slot>
  </div>
</template>

slot 中还可以作为一个作用域,在子组件中定义变量,然后在父组件中自定义渲染的方式:(项目中使用的比较多,vue+elementUI中ajax获取数据显示在表格中,很多时候每一条数据不是直接显示的,需要做一些额外的处理)

子组件
<template>
  <div class="headComponent">
    <h3>这是一个头部组件</h3>
    <slot name="head" v-for="head in heads" :text="head.text"></slot>
  </div>
</template>
父组件
<head-component>
	<template slot="head" scope="props">
		<li> {{ props.text }} </li>
	</template>
</head-component>

参考链接:vue组件化开发_star@星空的博客-CSDN博客

Vue公共组件的封装_Milly_Liu的博客-CSDN博客_vue公共组件的封装

vue组件化开发_star@星空的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-449458.html

到了这里,关于Vue组件化开发--公共组件的封装的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Vue】Vite 组件化开发

    1. 什么是组件化开发 组件化开发指的是:根据封装的思想,把页面上可重用的部分封装为组件,从而方便项目的开发和维护。 例如:https://gitee.com/vdpadmin/variant-form 所展示的效果,就契合了组件化开发的思想。用户可以通过拖拽组件的方式,快速生成一个页面的布局结构。

    2024年02月10日
    浏览(48)
  • 前端Vue入门-day03-用Vue实现工程化、组件化开发

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 生命周期 Vue 生命周期 和 生命周期的四个阶段  Vue 生命周期函数(钩子函数) 案例-create的应用 案例-mounted的应用 工程化开发 脚手架 Vue CLI 开发 Vue 的两种方式 基本介

    2024年02月15日
    浏览(58)
  • 【vue2第九章】组件化开发和根组件以及style上的scoped作用

    组件化开发和根组件 什么是组件化开发? 一个页面可以拆分为多个组件,每个组件有自己的 样式,结构,行为 ,组件化开发的好处就是,便于维护,利于重复利用,提升开发的效率。 便于维护 :页面中块出了问题,可以直接去找到这个组件,修改组件的样式逻辑结构。

    2024年02月10日
    浏览(53)
  • 低代码开发之vue.draggable的使用(初阶:组件化拖拽生成简单页面)

    效果展示 vue.draggable 安装 使用 vue.draggable 相关属性 事件 Demo完整代码 更多详见draggable官网=https://www.itxst.com/vue-draggable/tutorial.html

    2024年02月19日
    浏览(40)
  • 低代码开发之vue.draggable的使用(进阶:组件化拖拽生成功能页面)

    效果展示: 前言:随着各公司定制化需求的不断攀升,公司对低代码、组态化的开发需求日渐迫切。也许是研发任务节点将至,也许是为顺应时代潮流,我也是去学习并实践了一番。如图所示。 功能简介: 左侧组件区域特意做了选中态,小眼睛预览浮框态等交互,右侧内容区

    2024年03月23日
    浏览(52)
  • Vue(组件化编程:非单文件组件、单文件组件)

    传统组件编写:不同的HTML引入不同的样式和行为文件 组件方式编写:组件单独, 复用率高(前提组件拆分十分细致)  理解为封装行为:html,css,js封装在一个文件中 解释模块化和组件化的区别: 组件化 :css,js,html三件套使用在同一部分的代码封装在一个组件中 模块化

    2024年02月01日
    浏览(52)
  • 二、Vue组件化编程

    Vue 中使用组件的三大步骤: 定义组件(创建组件) 注册组件 使用组件(写组件标签) 如何定义一个组件? 使用 Vue.extend(options) 创建,其中 options 和 new Vue(options) 时传入的那个 options 几乎一样,但也有点区别; 区别如下: el 不要写,为什么? ——— 最终所有的组件都要经过一

    2024年02月22日
    浏览(45)
  • VUE3 --->组件化

    目录 vue-cli 1、基于 vue ui 创建 vue 项目  组件库 1.vue 组件库 2.vue 组件库和 bootstrap 的区别 3. 最常用的 vue 组件库 4. Element UI axios 拦截器 1. 回顾:在 vue3 的项目中全局配置 axios 2. 在 vue2 的项目中全局配置 axios 3、拦截器 4. 配置请求拦截器 5、配置响应拦截器 proxy 跨域代理 1. 回

    2024年02月15日
    浏览(35)
  • 通用vue组件化登录页面

    1.首先建立一个login文件夹,在里面建立对应的login.vue文件 2.设置登录页面的背景图,在App.vue文件中使用router-view进行展示登录组件 3.先给App.vue的div元素设置高度100%,之后在login.vue里面去设置背景图 这里注意怎么使login组件垂直水平居中的样式 1.首先建立一个cpns的文件夹,里

    2024年02月09日
    浏览(42)
  • 组件化开发复习

    createApp 函数传入了一个对象 App ,这个对象其实本质上就是一个组件,也是我们应用程序的根组件 可以写为:  我们先来学习一下全局组件的注册:  全局组件需要使用我们全局创建的 app 来注册组件;  通过 component 方法传入组件名称、组件对象即可注册一个全局组件了;

    2024年02月15日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包