vue把el-dialog提取出来作为子组件,并实现父组件和子组件相互传值

Posted 贺包蛋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue把el-dialog提取出来作为子组件,并实现父组件和子组件相互传值相关的知识,希望对你有一定的参考价值。

最近做项目遇到了一个需求是,为了防止组件中代码冗长,需要将el-dialog对话弹出框单独封装成子组件,并将父组件中的id传递给子组件,子组件再根据id刷新父组件。具体项目代码太长,这里仅记录一下实现思路。

01 把el-dialog提取出来作为子组件

效果如下

父组件

<template>
  <div>
    <!-- 1. 父组件template中注册子组件 -->
    <dialog-update ref="dialogUpdate"/>
  </div>
</template>

<script>
export default 
  components: 
    // 2. 父组件components中引入子组件
    DialogUpdate: () => import('./updateContent')
  ,
  methods: 
    // 按钮点击事件
    clickUpdate() 
        // 3. this.$refs获取子组件属性,设置属性为可见
        this.$refs.dialogUpdate.visible = true
    
  

</script>

子组件

<template>
  <el-dialog :visible.sync="visible">
  </el-dialog>
</template>

02 父组件向子组件传值,子组件刷新父组件

子组件的props属性接收父组件的传参
子组件用this.$emit()调用父组件的属性和方法

父组件

<template>
  <div>
    <!-- 1. 父组件将maintainId传给子组件,并为getContentInfo()开启监听事件 -->
    <dialog-update
      ref="dialogUpdate"
      :maintain-id="maintainId"
      @getContentInfo="getContentInfo"
    />
  </div>
</template>

<script>
export default 
  components: 
    DialogUpdate: () => import("./updateContent"),
  ,
  methods: 
    clickUpdate() 
      this.$refs.dialogUpdate.visible = true;
    ,
    getContentInfo(maintainId) 
        // 根据maintainId查询数据
    
  ,
;
</script>

子组件

<template>
  <el-dialog :visible.sync="visible"></el-dialog>
</template>

<script>
export default 
  // 2. 子组件props属性接收父组件的传参
  props: 
    maintainId: null,
  ,
  methods: 
    // 点击提交
    submit() 
      // 3. 子组件this.$emit()刷新父组件, 即getContentInfo(this.maintainId)
      this.$emit("getContentInfo", this.maintainId);
    ,
  ,
;
</script>

this.$parent也可以用于子组件获取父组件的属性和方法,但是注意,此时子组件必须放在父组件的根div下,否则undefined

// 父组件
<template>
	<div>
		// 子组件
		<dialog-update ref="dialogUpdate" />
	</div>
</template>
// 子组件的方法中调用父组件的method1方法
this.$parent.method1

如果子组件外层有ui组件包裹,那么子组件使用this.$parent获取父组件的属性和方法时,有几层ui组件,多几个.$parent

// 父组件
<template>
	<div>
		<el-dialog>
			// 子组件
			<dialog-update ref="dialogUpdate" />
		</el-dialog>
	</div>
</template>
// 子组件的方法中调用父组件的method2方法
this.$parent.$parent.method2

Vue2 + ElementUI 关于$emit用法总结

数据传递总结

  • 父组件可以使用 props 把数据传给子组件。
  • 子组件可以使用 $emit 触发父组件的自定义事件。

实战:封住客户等级功能的通用表单(支持新增和编辑)

定义封住子组件:levelCommon.vue

<style>
</style>
<template>
     <el-dialog :title="title" :visible="visible" size="tiny">
             <el-form ref="LevelForm" :model="level" :rules="rules" label-width="80px" >
                    <el-form-item label="等级名称" prop="name" >
                        <el-col :span="7">
                            <el-input v-model="level.name" auto-complete="off" ></el-input>
                        </el-col>
                    </el-form-item>
                    <el-form-item label="等级标识" >
                        <el-col :span="7">
                            <el-select v-model="level.mark" value-key="id" prop="mark">
                                <el-option v-for="item in markArry"  :key="item.id" :label="item.name" :value="item.id"></el-option>
                            </el-select>
                        </el-col>
                    </el-form-item>
                    <el-form-item label="等级描述" >
                        <el-col :span="7">
                            <el-input v-model="level.introduction" prop="introduction" auto-complete="off"></el-input>
                        </el-col>
                    </el-form-item>
            </el-form>
               <template slot="footer" class="dialog-footer">
                        <el-button @click="handleVisibleChange(false)">取 消</el-button>
                        <el-button type="primary" @click="handleSave">确 定</el-button>
                </template>
     </el-dialog>
</template>
 
<script>
export default{
    name: "LevelForm",
    // 用来接收父组件传给子组件的数据
    props: {
      // 是否显示表单
      visible: {
        type: Boolean,
        default: false
      },
      // 弹窗的title
      title: String,
      // 回显数据
      model: {
        type: Object,
        default: null
      }
    },
     data() {
      return {
        level: {
          id: '',
          mark: '',
          name: '',
          introduction: ''
        },
        rules: {
          name: {required: true, message: '请输入姓名', trigger: 'blur'},
          mark: {required: true, message: '请输入标记', trigger: 'blur'},
          introduction: {required: true, message: '请输入描述', trigger: 'blur'}
        },
        markArry:[
            {
                "id": 1,
                "name": '启用'
            },
            {
                "id": 2,
                "name": '删除'
            }
        ]
      }
    },
    watch: {
      // 监听 编辑时回显表单
      model(levelInfo) {
          this.level = {...levelInfo} // 简单的浅克隆
        }
    },
    methods: {
      handleSave() {
        // 表单验证 返回数据
        this.$refs.LevelForm.validate((valid) => {
          if (valid) {
            // 调用父类组件相关方法
            this.$emit('save', this.level)
            // 实体对象重置
            this.level ={}
          }
        })
      },
      handleVisibleChange(value) {
        this.$emit('update:visible', value)
      }
    }
}
</script>

组件调用

<style>
</style>
<template>
      <el-card class="full-height full-width">
        <search-table class="full-height full-width"
            :table-loading="loading"
            :tableData="tableData"
            :ref="tableRef"
            :labelWidth="'40px'"
            :row-keys="row => row.id"
            @query="currentPage = 1; query();"
            @reset="doReset"
            @selectionChange="selectionChange">
            <template v-slot:row>
                <el-form-item label="名称">
                    <el-input placeholder="请输入名称" v-model="searchForm.name" clearable></el-input>
                </el-form-item>
                <el-form-item label="标识">
                    <el-select placeholder="请选择" v-model="searchForm.mark" clearable>
                        <el-option :label="'启用'" :value="1"></el-option>
                        <el-option :label="'删除'" :value="2"></el-option>
                    </el-select>
                </el-form-item>
            </template>
            <template v-slot:actions>
                <el-button size="small" type="primary" v-on:click="addLevel()">新 建</el-button>
                <el-button size="small" type="primary" v-on:click="editLevel()">编 辑</el-button>
                <el-button size="small" type="primary" v-on:click="handlerDelete()">删除/批量删除</el-button>
            </template>
            <template >
                <el-table-column :reserve-selection="true" type="selection" width="55" />
                <el-table-column prop="name" label="名称" show-overflow-tooltip />
                <el-table-column prop="mark" label="标识" :formatter="formatMarkType" show-overflow-tooltip />
                <el-table-column prop="introduction" label="描述" show-overflow-tooltip />
            </template>
            <template v-slot:footer>
                <el-pagination
                    background
                    :current-page="currentPage"
                    :page-sizes="pageSizes"
                    :page-size="pageSize"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="total"
                     @size-change="handleSizeChange"
                     @current-change="handleCurrentChange" />
            </template>
        </search-table>
 
        <levelCommon
             title="新增客户等级"
            :visible.sync="dialogFormAdd"
            @save="add" // 执行父类组件的add 方法
        ></levelCommon>
 
        <levelCommon
            :model="level"
             title="修改客户等级"
            :visible.sync="dialogFormEdit"
            @save="edit" // 执行父类组件的edit方法
        ></levelCommon>
 
      </el-card>
 
      
 
 
</template>
<script>
import SearchTable from '@/components/searchTable'
import levelCommon from '../levelCommon'
import { Message} from "element-ui";
import {getLevelPage, batchLevelDelete, levelInsert, levelGetById, levelUpdate} from "@/api/level";
export default{
    name: 'customer',
    components: {
        SearchTable,
        levelCommon
    },
     data () {
        return {
            tableData: [],
            loading: false,
            tableRef: 'tableRef',
            searchForm: {},
            currentPage: 1,
            pageSizes: [10, 20, 50],
            pageSize: 10,
            total: 0,
            selectionList:[], //定义删除/批量删除
            dialogFormAdd:false,
            dialogFormEdit: false,
            level:{
                id: '',
                name: '',
                introduction: '',
                mark: ''
            },
            markArry:[{
                "id": 1,
                "name": "启用"
            },{
                "id": 2,
                "name": "删除"
            }],
 
        };
    },
    created() {
      this.query()
    },
    methods: {
        query() {
            // 请求表格数据
        var params ={
          'pageNum': this.currentPage,
          'pageSize': this.pageSize,
          'name':this.searchForm.name,
          'mark':this.searchForm.mark
         }
        getLevelPage(params).then(res => {
                console.log(res)
                // 把请求到的数据给testDatas数组
                this.tableData = res.data.list
                // 当前页数
                this.currentPage = res.data.pageNum
                // 当前页数量
                this.pageSize = res.data.pageSize
                // 分页总数
                this.total = res.data.total
              //   console.log(JSON.stringify(res.data.data.total))
            })
            .catch((error) => {
             console.log(error)
            })
 
        },
        doReset() {
            // 重置搜索条件
             // 请求表格数据
              this.tableData = [];
              this.restForm();
              this.query();
        
 
        },
        restForm(){
            this.searchForm.name = ""
            this.searchForm.mark = ""
        },
        selectionChange(val) {
            // 表格选项发生变化
            console.log("触发表格事件")
 
            this.selectionList = []
		    val.forEach(element => {
		        this.selectionList.push(element.id)
		    });
          
        },
        handlerDelete(){
              // 数组转字符串使用逗号分隔
            let sids =  this.selectionList.join(",")
            var params ={
                'sids': sids
            }
            batchLevelDelete(params).then(res =>{
                Message({
                    message: '批量删除成功',
                    type: 'success',
                    duration: 3 * 1000
                })
                // 重新查询表格
                this.query()
            }).catch((error) => {
             console.log(error)
            })
            
        },
        handleSizeChange(val) {
            // 改变每页条数
            this.pageSize = val
            this.query()
        },
        handleCurrentChange(val) {
            // 切换页码
            this.currentPage = val
            this.query()
        },
        // table 数据转换
        formatMarkType(row, column){
             if(row.mark === 1){
                     return '启用'
                 } else if(row.mark === 2) {
                     return '删除'
                 } else {
                     return ''
                 }
        },
        // 新增客户
        addLevel(){
            this.dialogFormAdd = true
            this.level = {}
        },
        // 修改客户
        editLevel(){
            let id = this.selectionList[0]
             var params = {
                 'id' : id
             }
            levelGetById(params).then(res =>{
                // 
                this.level = {}
                this.level = res.data
                this.dialogFormEdit = true
              
            }).catch((error) => {
                console.log(error)
            })
            
        },
     
        add(level){
            console.log(level)
            levelInsert(level).then(res =>{
                 Message({
                    message: '客户等级新增成功',
                    type: 'success',
                    duration: 3 * 1000
                })
                // 新增弹出框隐藏
                this.dialogFormAdd = false
                // 重新查询表格
                this.query()
            }).catch((error) => {
             console.log(error)
            })
        },
        edit(level){
             levelUpdate(level.id, level).then(res =>{
                 Message({
                    message: '客户等级修改成功',
                    type: 'success',
                    duration: 3 * 1000
                })
                // 新增弹出框隐藏
                this.dialogFormEdit = false
                // 重新查询表格
                this.query()
            }).catch((error) => {
             console.log(error)
            })
        }
    }
}
</script>

以上是关于vue把el-dialog提取出来作为子组件,并实现父组件和子组件相互传值的主要内容,如果未能解决你的问题,请参考以下文章

vue里面的父子通信

vue.js组件之j间的通讯一 子组件接受父祖件数据

Vue——每次弹出el-dialog,都会执行mounted

elementui解决el-dialog不清空内容的问题,el-dialog关闭时销毁子组件

二次封装el-dialog组件

sync分析之为啥el-dialog中的visible需要使用.sync