vue2.0 自定义组件的方法(vue组件的封装)


Posted in Javascript onJune 05, 2018

一、前言

之前的博客聊过 vue2.0和react的技术选型;聊过vue的axios封装和vuex使用。今天简单聊聊 vue 组件的封装。

vue 的ui框架现在是很多的,但是鉴于移动设备的复杂性,兼容性问题突出。像 Mint-UI 等说实话很不错了,但是坑也是不少,而且很多功能也是仅凭这些实现不了,这需要我们去封装自己的可复用组件

二、封装组件的步骤

1. 建立组件的模板,先把架子搭起来,写写样式,考虑你的组件的基本逻辑。

os:思考1小时,码码10分钟,程序猿的准则。

2. 准备组件的好数据输入。即分析好逻辑,定好 props 里面的数据、类型。(后面详解)

3.准备组件的好数据输出。即根据组件逻辑,做好要暴露出来的方法。(后面详解)

4.封装完毕了,直接调用即可。

os: 代码可以不看,结论在文章最后

接下来以一个很简单的例子具体说明一下

现在先看一下demo的效果图

 vue2.0 自定义组件的方法(vue组件的封装)

三、 demo代码

父组件:

<template>
 <section class="f-mainPage">
 <!--selectFunc 选择完成的回调 searchList 下拉列表的数据-->
 <search @selectFunc="selectFunc" :searchList="searchList" :selectValue="selectValue"></search>
 </section>
</template>

<script type="text/ecmascript-6">
 import Search from '../vuePlugin/search'
 export default {
 data() {
 return {
 searchList: ['草船借箭', '大富翁', '测试数据'],
 // 直接通过props传递对象 修改,挺便捷的,但是不规范
 selectValue: {
  data: '1'
 },
 // 通过emit修改,规范写法
 selectValue2: ''
 }
 },
 mounted() {},
 methods: {
 pageGo(path) {
 this.$router.push('/' + path)
 },
 selectFunc(value) {
 this.selectValue2 = value
 console.log(this.selectValue)
 console.log(this.selectValue2)
 }
 },
 components: {
 Search
 }
 }
</script>

<style lang="scss" scoped>
.f-mainPage{
 width: 100%;
 .g-banner{
 width: 100%;
 background-image: url(../../../static/main_bg.png);
 background-repeat: no-repeat;
 background-size: 100% 100%;
 position: relative;
 overflow: hidden;
 color: white;
 text-align: center;
 p:nth-child(1) {
 margin: 10px auto 0px auto;
 font-size: 1.3rem;
 }
 .f-banscri {
 margin: 15px auto 8px auto;
 font-size: 0.95rem;
 }
 .f-moneyMax{
 margin: 5px auto 0px auto;
 font-size: 2.4rem;
 }
 .f-returnCash{
 width: 120px;
 height: 35px;
 text-align: center;
 line-height: 35px;
 background-color: white;
 color: #169BD5;
 display: inline-block;
 border-radius: 5px;
 font-size: 1rem;
 margin-top: 35px;
 position: relative;
 .f-mmmbd{
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: transparent;
  top: 0;
  left: 0;
 }
 }
 }
 .g-cashInfor{
 width: 100%;
 text-align: center;
 display: flex;
 justify-content: space-between;
 div{
 width: 50%;
 height: 60px;
 line-height: 60px;
 box-sizing: border-box;
 }
 div:nth-child(1){
 border-bottom: 1px solid #878787;
 border-right: 1px solid #878787;
 }
 div:nth-child(2){
 border-bottom: 1px solid #878787;
 }
}
 .g-operate{
 width: 100%;
 height: auto;
 overflow: hidden;
 ul{
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 1.05rem;
  li{
  height: 60px;
  line-height: 60px;
  padding-left: 25px;
  position: relative;
  span{
   width: 20px;
   height: 20px;
   position: absolute;
   top: 20px;
   right: 20px; 
   background-image: url(../../../static/go.png);
   background-repeat: no-repeat;
   background-size: 100% 100%;
  }
  }
 }
 .f-goodNews{
  width: 340px;
  height: 144.5px;
  margin: 20px auto 30px auto;
  text-align: center;
  background-image: url(../../../static/banner.png);
  background-repeat: no-repeat;
  background-size: 100% 100%;
 }
 }
}
</style>

子组件:

<template>
 <div class="searchZJ">
 <div class="f-search">
  <div class="f-searchIn" v-bind:class="{searchInFous: this.fousFlag}">{{this.searchValue}}<span v-bind:class="{searchActive: this.searchFlag}" v-on:click="searchDown"></span></div>
  <div class="f-searchXl" v-if="this.dataHas" v-bind:style="{height:this.searchFous, border:this.searchBorder}">
  <div v-for="item in searchList" v-on:click="choseValue(item)">{{item}}</div>
  </div>
  <div class="f-searchXl" v-else >
  <div>暂无数据</div>
  </div>
 </div>
 </div>
</template>
<script type="text/ecmascript-6">
 export default {
 data() {
 return {
 data: [],
 dataHas: true,
 searchFlag: false,
 searchFous: '0',
 fousFlag: false,
 searchValue: '',
 searchBorder: 'none'
 }
 },
 props: {
 searchList: Array,
 selectValue: Object
 },
 mounted() {
 this.data = this.searchList
 },
 methods: {
 searchDown() {
 this.searchFlag === false ? this.searchFlag = true : this.searchFlag = false
 this.searchFous === '0' ? this.searchFous = 'auto' : this.searchFous = '0'
 this.searchBorder === 'none' ? this.searchBorder = '1px solid #D9D9D9' : this.searchBorder = 'none'
 this.fousFlag === false ? this.fousFlag = true : this.fousFlag = false
 },
 choseValue(value) {
 this.searchValue = value
 this.searchDown()
 this.selectValue.data = '我被修改了'
 this.$emit('selectFunc', value)
 }
 }
 }
</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
 .f-search{
 width: 250px;
 height: auto;
 position: relative;
 margin-left: 20px;
 box-sizing: border-box;
 }
 .f-searchIn{
 width: 250px;
 height: 35px;
 line-height: 35px;
 font-size: 0.95rem;
 border-radius: 5px;
 overflow: hidden;
 position: relative;
 background-color: white;
 box-shadow: none;
 box-sizing: border-box;
 color: #000000;
 padding-left: 10px;
 border: 1px solid #A3A3A3;
 }
 .searchInFous{
 border: 1px solid #57C4F6;
 box-shadow: 0px 0px 5px #57C4F6;
 }
 .f-searchIn > span{
 display: block;
 width: 28px;
 height: 28px;
 background-image: url(../../../static/upDown.png);
 background-size: 100% 100%;
 background-repeat: no-repeat;
 background-position: 0px -13px;
 position: absolute;
 top: 10px;
 right: 5px;
 }
 .f-searchIn .searchActive{
 background-position: 0px 12px;
 top: -2px;
 }
 .f-search .f-searchXl{
 position: absolute;
 width: 100%;
 height: auto;
 max-height: 220px;
 top: 41px;
 left: -1px;
 border-radius: 5px;
 /*border: 1px solid #D9D9D9;*/
 background-color: white;
 overflow-x: hidden;
 overflow-y: scroll;
 }
 .f-search .f-searchXl > div{
 height: 35px;
 line-height: 38px;
 color: #000000;
 padding-left: 25px;
 font-size: 0.92rem;
 }
 .f-search .f-searchXl > div:hover{
 background-color: #D5F1FD;
 }
</style>

四、代码详解

1. 先说一下 props

我们在父组件中需要将子组件需要的数据导入,用法如下:

<search @selectFunc="selectFunc" :searchList="searchList" :selectValue="selectValue"></search>

:searchList ="searchList"  就是我们的数据,这个可以写多个。这里我传输了2个参数过去,主要是做数据修改的说明。大家可以先忽略。

在子组件中,我们的接收和使用方法如下:

props: {
 searchList: Array,
 selectValue: Object
 },
mounted() {
 this.data = this.searchList
 },

我们在 props 中接收数据,注意props对象里面 键值 是对改数据的 数据类型 的规定。做了规范,使用者就只能传输指定类型的数据,否则报警告

二props对象中的数据,我们可以直接在当前组件中使用   this.searchList,可以直接使用。至于原理嘛,不懂的可以取脑补一下 js的原型 。os:这些基础,在这就不做详述了

以上就是props传递过来的数据的使用了。

2. emit的使用(如何暴露组件方法)

我们已经会使用 父组件向子组件传数据了,那如子组件如何来修改父组件的数据呢?

这里提供 2 种实现方法,但是 第一种不推荐,强烈不推荐

方式一:

 selectValue: {
  data: '1'
 },


。。。。。。。。。。。。。。。
 this.selectValue.data = '我被修改了'

即,父组件将 对象 数据传递给子组件,子组件直接修改props过来的对象的值

可以实现,感觉是一个比较快捷的方式。但是不推荐,这种方式写多了,容易出错,特别是多层组件嵌套的时候。这种修改对代码的迭代和错误的捕捉都不友好,所以建议大家别这样写。

他的实现原理简单提一下: 这个对象、数组啦,是引用数据类型,说白了,就是存储单元的信息是指针,真正数据在别的地方,通过指针查询的数据,所以这样写,对浏览器来说仅仅是传递了一个指针,数据还是同一份数据。所以你能修改。

方式二:

正儿八经的通过 $emit 方法去掉父组件的方法,在父组件中修改data的数据。(根正苗红的方法,规范写法)

// 子组件
this.$emit('selectFunc', value)
// 父组件
<search @selectFunc="selectFunc" :searchList="searchList" :selectValue="selectValue"></search>
selectFunc(value) {
 this.selectValue2 = value
 console.log(this.selectValue)
 console.log(this.selectValue2)
 }

将父组件的方法注入子组件   @selectFunc ="selectFunc" ,然后在子组件中通过 $emit 调用他,并传递参数。达到修改的目的。

五、 总结

这里主要是总结一下vue组件封装的思路,帮大家梳理一下。很简单,和jQuery插件、react组件一样,所有组件都是一个套路,就是 函数思想。

组件就是做烤肠台机器,我放进去猪肉,再按一下各种开关,然后你给我烤肠。

1. 定义好 你需要使用者传入的数据

2. 定义好 你提供给使用者的方法

3. 写好组件的内部逻辑

这就OK了,一个完美的,可复用的组件就完成了。    os: 在此吐槽一下,那些自认为是优秀的组件,其实,别人拿着没法用的代码。

以上所述是小编给大家介绍的vue2.0 自定义组件的方法(vue组件的封装),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jQuery使用手册之三 CSS操作
Mar 24 Javascript
JQuery 风格的HTML文本转义
Jul 01 Javascript
JavaScript 常见对象类创建代码与优缺点分析
Dec 07 Javascript
js 兼容多浏览器的回车和鼠标焦点事件代码(IE6/7/8,firefox,chrome)
Apr 14 Javascript
JS使用for循环遍历Table的所有单元格内容
Aug 21 Javascript
js实现类似jquery里animate动画效果的方法
Apr 10 Javascript
快速使用Bootstrap搭建传送带
May 06 Javascript
JS前端加密算法示例
Dec 22 Javascript
jQuery接受后台传递的List的实例详解
Aug 02 jQuery
基于jQuery实现图片推拉门动画效果的两种方法
Aug 26 jQuery
vue移动端实现下拉刷新
Apr 22 Javascript
vue 实现根据data中的属性值来设置不同的样式
Aug 04 Javascript
vue使用技巧及vue项目中遇到的问题
Jun 04 #Javascript
jQuery实现的滑块滑动导航效果示例
Jun 04 #jQuery
jQuery实现常见的隐藏与展示列表效果示例
Jun 04 #jQuery
js如何找出字符串中的最长回文串
Jun 04 #Javascript
详解Webpack + ES6 最新环境搭建与配置
Jun 04 #Javascript
jQuery实现的简单获取索引功能示例
Jun 04 #jQuery
JS实现统计字符串中字符出现个数及最大个数功能示例
Jun 04 #Javascript
You might like
作为PHP程序员应该了解MongoDB的五件事
2013/06/03 PHP
利用yahoo汇率接口实现实时汇率转换示例 汇率转换器
2014/01/14 PHP
PHP中is_file不能替代file_exists的理由
2014/03/04 PHP
PHP中实现crontab代码分享
2015/03/26 PHP
php实现模拟登陆方正教务系统抓取课表
2015/05/19 PHP
php微信开发之音乐回复功能
2018/06/14 PHP
PHP关于foreach复制知识点总结
2019/01/28 PHP
thinkphp5框架前后端分离项目实现分页功能的方法分析
2019/10/08 PHP
jquery json 实例代码
2010/12/02 Javascript
jQuery 选择表格(table)里的行和列及改变简单样式
2012/12/15 Javascript
购物车选中得到价格实现示例
2014/01/26 Javascript
Vue.js每天必学之构造器与生命周期
2016/09/05 Javascript
JavaScript 总结几个提高性能知识点(推荐)
2017/02/20 Javascript
js Date()日期函数浏览器兼容问题解决方法
2017/09/12 Javascript
jQuery中 DOM节点操作方法大全
2017/10/12 jQuery
详解angular应用容器化部署
2018/08/14 Javascript
JS实现计算小于非负数n的素数的数量算法示例
2019/02/26 Javascript
详解vue2.6插槽更新v-slot用法总结
2019/03/09 Javascript
NodeJS http模块用法示例【创建web服务器/客户端】
2019/11/05 NodeJs
[09:37]2018DOTA2国际邀请赛寻真——不懈追梦的Team Serenity
2018/08/13 DOTA
Python编程修改MP3文件名称的方法
2017/04/19 Python
numpy实现RNN原理实现
2021/03/02 Python
LocalStorage记住用户和密码功能
2017/07/24 HTML / CSS
英国最大的网上药品商店:Chemist Direct
2017/12/16 全球购物
全球销量第一生发产品:Viviscal
2017/12/21 全球购物
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
2013/07/26 面试题
《桂林山水》教学反思
2014/02/08 职场文书
运动会广播稿20字
2014/02/18 职场文书
采购求职信
2014/03/17 职场文书
英文演讲稿
2014/05/15 职场文书
小学校园文化建设汇报材料
2014/08/19 职场文书
珠宝的促销活动方案
2014/08/31 职场文书
安全生产月宣传标语
2014/10/06 职场文书
Javascript中的解构赋值语法详解
2021/04/02 Javascript
pytorch 两个GPU同时训练的解决方案
2021/06/01 Python
Flink 侧流输出源码示例解析
2022/09/23 Servers