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实现自定义弹窗示例
Mar 12 Javascript
js实现ifram取父窗口URL地址的方法
Feb 09 Javascript
jQuery插件slick实现响应式移动端幻灯片图片切换特效
Apr 12 Javascript
js如何判断访问是来自搜索引擎(蜘蛛人)还是直接访问
Sep 14 Javascript
JS实现新浪微博效果带遮罩层的弹出框代码
Oct 12 Javascript
jquery 中toggle的2种用法详解(推荐)
Sep 02 Javascript
JS访问DOM节点方法详解
Nov 29 Javascript
微信小程序模板和模块化用法实例分析
Nov 28 Javascript
js传递数组参数到后台controller的方法
Mar 29 Javascript
Vue.set 全局操作简单示例
Sep 19 Javascript
Vue中通过属性绑定为元素绑定style行内样式的实例代码
Apr 30 Javascript
微信小程序input抖动问题的修复方法
Mar 03 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数据库类
2009/05/27 PHP
PHP 用数组降低程序的时间复杂度
2009/12/04 PHP
php 修改zen-cart下单和付款流程以防止漏单
2010/03/08 PHP
php替换超长文本中的特殊字符的函数代码
2012/05/22 PHP
thinkphp3.0 模板中函数的使用
2012/11/13 PHP
PHP实现加强版加密解密类实例
2015/07/29 PHP
php获取当前页面完整URL地址
2015/12/30 PHP
Thinkphp连表查询及数据导出方法示例
2016/10/15 PHP
setinterval()与clearInterval()JS函数的调用方法
2015/01/21 Javascript
jQuery实现tab标签自动切换的方法
2015/02/28 Javascript
jquery.validate使用时遇到的问题
2015/05/25 Javascript
前端页面文件拖拽上传模块js代码示例
2017/05/19 Javascript
vue.js删除动态绑定的radio的指定项
2017/06/02 Javascript
JavaScript学习笔记之惰性函数示例详解
2017/08/27 Javascript
mint-ui 时间插件使用及获取选择值的方法
2018/02/09 Javascript
基于express中路由规则及获取请求参数的方法
2018/03/12 Javascript
Vue2.0点击切换类名改变样式的方法
2018/08/22 Javascript
vue项目每30秒刷新1次接口的实现方法
2018/12/04 Javascript
Vue管理系统前端之组件拆分封装详解
2020/08/23 Javascript
Python结巴中文分词工具使用过程中遇到的问题及解决方法
2017/04/15 Python
分享几道你可能遇到的python面试题
2017/07/24 Python
python利用lxml读写xml格式的文件
2017/08/10 Python
将字典转换为DataFrame并进行频次统计的方法
2018/04/08 Python
在交互式环境中执行Python程序过程详解
2019/07/12 Python
Django接收自定义http header过程详解
2019/08/23 Python
Python图片处理模块PIL操作方法(pillow)
2020/04/07 Python
Python 操作 MySQL数据库
2020/09/18 Python
Html5页面获取微信公众号的openid的方法
2020/05/12 HTML / CSS
英国100%防污和防水的靴子:Muck Boot Company
2020/09/08 全球购物
方正Java笔试题
2014/07/03 面试题
在校生钳工实习自我鉴定
2013/09/19 职场文书
银行开户授权委托书格式
2014/10/10 职场文书
一次性工伤赔偿协议书范本
2014/11/25 职场文书
婚庆司仪开场白
2015/05/29 职场文书
2019年幼儿园管理条例范本!
2019/07/17 职场文书
《哪吒之魔童降世》观后感:世上哪有随随便便的成功
2019/11/08 职场文书