Vue自定义组件 & 前端初学习心得

12 篇文章 0 订阅

Vue自定义组件 & 前端初学习心得

小总结

最近在老板公司实习,第一周要搞后端,完成增删改查工作;待测试好所有后台接口之后,第二周又要在该项目上搞前端。后端框架Mybatis+springMVC我还比较熟悉,上手没什么难度,但是对于前端框架vue-admin-template + element-ui,虽然我之前也写过些前端,但都是一个人单干的那种(用bootstrap + vue源),没人教也没人能问,因此对于这个全新的框架,我还是花了不少心思去学习,去讨教。下面谈谈我的心得吧,也算是对自己这几周实习的总结。

如何快速上手干一个页面

  • 前端要上手快,不单单要掌握必备知识,还要对页面的结构,要实现的业务逻辑要了如指掌(学前端一定要把知识和业务逻辑建立关系,不是单纯停留在框架的使用上!!!),这个按键对应了自己定义的哪个函数要记住。而且定义的方法一定要有注释,功能,逻辑要写清楚,对应的是哪个控件的,也要写清楚。

为什么要封装组件

  • 虽然页面看上去是一个整体,但是其中是有层级结构的,是由各个具有嵌套关系的组件(即函数)构成的。
    在这里插入图片描述
  • 要封装成组件,即需要向外暴露参数接口,便于动态调整组件里的值
  • 设计前端组件其实是一种模块化思维,将复杂的东西集成到一个小组件中,既方便修改,也方便复用。在实际开发时,常常对原生组件进行二次封装,比如接下来要封装的组件是在element-ui中的<el-tree>上进行二次封装。
  • 组件其实就是一个函数,通过定义组件的形参,向父组件提供可供调用的接口。函数的返回值,可以通过父组件传递给子组件的函数,实现子组件的回调,给父组件赋值。( 回调函数(callback)是什么?
  • 对组件的学习,可以看看市面上常用组件的源码(element-ui),看它是怎么封装的,提供了哪些参数,暴露了哪些方法。

自定义组件核心

参考

1、封装组件的步骤
  1. 准备好组件的数据输入。即分析好逻辑,定好 props 里面的数据、类型(父组件可以使用 props 把数据传给子组件,props里定义的参数就是形参)

  2. 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法,方便父组件去获取子组件的引用,得到子组件对象,调用子组件的方法。

  3. 子组件可以使用 $emit, 给父组件的函数传递参数,实现父组件中值的修改 。(可以简单理解成组件的输出接口,实际上利用回调函数告知父组件已完成任务

2、参数传递

在父组件中使用子组件<TreeCheckbox>(该名字与父组件注册的子组件名字一致)

<!--父组件-->
<TreeCheckbox 
             style="width:270px;background-color: #272727;"
             :expanded_keys="expanded_keys"
             :checked_keys="checked_keys"
             :props="defaultProps"
             @checkboxSelected="checkboxSelected"
             >
</TreeCheckbox>

其中:expanded_keys:checked_keys:props可以理解成子组件中的形参,这些形参是在props中定义的,每个形参都有:

<!--子组件-->
<template>
   <el-tree
       ref="tree"
       :data="data"
       show-checkbox
       :node-key="defaultProps.value"
       :default-expanded-keys="expanded_keys"
       :default-checked-keys="checked_keys"
       :props="defaultProps"
       @check="handleCheckChange()"> 
   </el-tree>
</template>
<script>
   export default {
       props:{
       //组件参数配置项,用于封装前端组织树结构
       defaultProps: {
         type: Object,
         default: () => {
           return {
             value: 'id', // ID字段名
             label: 'label', // 显示名称
             children: 'children', // 子级字段名
           }
         },
       },

       //默认展开的节点的 key 的数组
       expanded_keys: {
         type: Array,
         default: () => {
           // return ['1-1','1-2']
           return []
         },
       },

       //默认勾选的节点的 key 的数组
       checked_keys: {
         type: Array,
         default: () => {
           // return ['1-1','1-2']
           return []
         },
       },
     },
   }
</script>
3、emit的使用(如何暴露组件方法)

参考vue2.0 如何自定义组件(vue组件的封装/组件的二次封装)

我们已经会使用 父组件向子组件传数据了,那如子组件如何来修改父组件的数据呢?这里提供 2 种实现方法,但是 第一种不推荐,强烈不推荐(引用修改)

方式一:

//父组件
expanded_keys : []

//子组件
this.expanded_keys = ['0-1','1-1']  //'我被修改了'

即,父组件将 对象 数据传递给子组件,子组件直接修改props过来的对象的值。这种方法仅适用于Array,Object等引用类型,但在实际开发中,强烈不建议这么写!!!这种方式写多了,容易出错,特别是多层组件嵌套的时候。这种修改对代码的迭代和错误的捕捉都不友好

方式二:

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

// 子组件
<script>
   this.$emit('checkboxSelected',this.selectOptions); //select事件触发后,自动触发父组件的checkboxSelected事件
</script>

// 父组件
<el-form-item class="flex_row person_participate" label="参与人员" prop="ip">
   <TreeCheckbox 
                 style="width:270px;background-color: #272727;"
                 :expanded_keys="expanded_keys"
                 :checked_keys="checked_keys"
                 :props="defaultProps"
                 @checkboxSelected="checkboxSelected"
                 >
   </TreeCheckbox>
</el-form-item>

<script>
//参与人员复选框选中事件(会激活子组件向该父组件传值,并修改父组件的值)
   checkboxSelected(value){
       this.dialogForm.personOrgSelected = value
       alert(this.dialogForm.personOrgSelected)
   },
</script>

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

自定义组件注意点

1、组件声明 和 组件注册

父组件在使用子组件之前,

  • 不仅需要单独测试子组件的内部功能是否完整**(比如在子组件页面中,测试后台数据传值到页面是否存在问题)**
  • 还需要在父组件中导入子组件的包并对其重命名(组件声明),接着完成组件注册
<!--父组件-->
<script>
//导入方法或组件
import "@/utils/dateUtil";
import { organizationfindTreeList,organizationfindAll } from '@/api/organization/index'
import Pagination from "@/components/PagiNation";  //分页组件
// import TreeSelect from "@/components/TreeSelect"  //树形结构
import TreeCheckbox from "@/views/emergencyTrain/TreeCheckbox";   //参与人员树形结构(自定义的子组件)
import {
 //真实接口
 trainManageInsert,
 trainManageFileInsert,
 trainManageUpdate,
 trainManagefind,
 trainManageDel,
 trainManageInsertPersonal,
 trainManageFindPageList,
 personnelbyOrganization,
 trainPlanFindList,   //培训计划全查(无分页)
}from "@/api/tranplan/index"


export default {

 //组件注册
 components: {
   Pagination,
   // TreeSelect,
   TreeCheckbox  //注册自定义的子组件
 },
 data() {
   return {
   }
 }
}
</script>
2、子组件监听父组件的值是否发生修改

这里使用watch监听没用,参考vue子组件监听父组件传值

<script>
   export default{
      ...
      methods : {
          watch: {
             expanded_keys: {
               handler(val) {
                 console.log('expanded_keys deep change', val)
                 this.expanded_keys = val
               },
               deep: true, // 深度监听
               immediate: true, // 初次监听即执行  
             },
             //监听checked_keys
             checked_keys: {
               handler(val) {
                 console.log('checked_keys deep change', val)
                 this.checked_keys = val
               },
               deep: true, // 深度监听
               immediate: true, // 初次监听即执行  
             },
           },
      }
   }
</script>      

但是却存在bug:父组件值修改了,子组件也检测到父组件传进来参数(Array)的值发生修改,但是在回显的时候,即使expand_key为空,但是页面总是能回显出数据。这里使用vue生命周期中的updated()方法来检测当前的页面的值是否发生更新。

updated() {
   console.log("updated")
   console.log(this.expanded_keys)//获取到父组件传过来的值
   console.log(this.checked_keys)//获取到父组件传过来的值 
 }, 

在这里插入图片描述

从控制台可以看出,updated方法中打印出来的checked-key是个空数组,然而原生组件el-tree在使用checked-key回显复选框勾选状态时,却没有动态修改

主要原因是使用了default-checked-key,它只会初始化值,并不能在检测到值修改时,完成自动更新,因此需要获取原生组件(el-tree)对象,通过它提供的方法,手动修改checked_keys

updated() {
   console.log("updated")
   console.log(this.expanded_keys)//获取到父组件传过来的值
   console.log(this.checked_keys)//获取到父组件传过来的值
     
   this.$refs.tree.setCheckedKeys(this.checked_keys)   //如果父组件的值发生更新(子组件也能监听到),但是仍然需要获取原生组件<el-tree>的引用,实现赋值   
 }, 

这里的$refs.tree是对子组件中原生组件<el-tree>的引用

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值