vue中组件之间的通信--$emit

在这里插入图片描述
在本文中, 我主要写写$emit的一些用法和实例(笔记用)

1.用法

​ $emit( eventName, […args] )

​ eventName:一个事件名,会绑定一个方法。当组件触发事件后,将调用这个方法。
​ …args:附加参数,会被抛出,由上述绑定的方法接收使用。
文档说:它是一个触发当前实例上的事件。附加参数都会传给监听器回调。

​ 子组件使用this.$emit()向父组件传值。首先必须在父组件中引用子组件,然后实现传值。

1.1在父组件中引入子组件

使用import引入组件

​ import indexImportOrder from ‘./components/indexImportOrder’
声明

//定义组件
components:{
indexImportOrder,
},
使用

<indexImportOrder ref="indexImportOrder"/>

1.2 子组件向父组件传值

(1)在子组件中需要向父组件传值处使用this.$emit(“function”,param), function为父组件定义函数,param为需要传递参数。

//新订单页面跳转
viewBusiness(){
    let flag = false;
    this.$emit('closeMain',flag);
},

(2)在父组件中子组件引用处添加函数v-on:function=“function1”; 其中function为子组件中定义函数,function1为父组件定义函数–用于接收子组件传值并进行相应数据处理,可定义为同一名称

<indexImportOrder ref="indexImportOrder" v-on:closeMain="closeMain"/>

val及为子组件中flag,即接收的子组件参数

closeMain(val){
this.flag = val;
},

2.示例

2.1 只配合一个事件名使用$emit(‘welcome’),无附加参数

// 定义组件
Vue.component('welcome-button', {
  template: `
    <button v-on:click="$emit('welcome')">  	// 【1】 $emit只使用了一个事件名welcome,无参数
      Click me to be welcomed
    </button>
  `
})
//使用组件
<div id="emit-example-simple">
  <welcome-button v-on:welcome="sayHi"></welcome-button> 	// 【2】 为事件名welcome绑定一个方法sayHi
</div>

//创建Vue实例
new Vue({
  el: '#emit-example-simple',
  methods: {
    sayHi: function () {	// 【3】 当组件触发事件后,执行welcome所绑定的方法sayHi
      alert('Hi!')
    }
  }
})

2.2 配合额外的参数使用**

// 定义组件
Vue.component('magic-eight-ball', {
  data: function () {
    return {
      possibleAdvice: ['Yes', 'No', 'Maybe']
    }
  },
  methods: {
    giveAdvice: function () {
      var randomAdviceIndex = Math.floor(Math.random() * this.possibleAdvice.length)
      //【1】在组件绑定的方法giveAdvice中触发$emit事件,并抛出参数
      this.$emit('give-advice', this.possibleAdvice[randomAdviceIndex])  
    }
  },
  template: `
    <button v-on:click="giveAdvice">
      Click me for advice
    </button>
  `
})

// 使用组件
<div id="emit-example-argument">
  <magic-eight-ball v-on:give-advice="showAdvice"></magic-eight-ball> //【2】为$emit事件绑定一个方法showAdvice
</div>

// 创建Vue实例
new Vue({
  el: '#emit-example-argument',
  methods: {
    showAdvice: function (advice) {    // 【3】方法的参数 advice 用来接收 $emit 抛出的参数
      alert(advice)
    }
  }
})

2.3 利用组件来实现动态显示框的传值

应用:填写,修改信息时用到的动态显示框,增加用户友好体验感

这是一个简单的用户信息增删改的例子, 子组件专门写动态显示框的内容,父组件和子组件之间利用$emit来传递用户对象, 或用来触犯父组件中的函数

views/demo.vue部分(父组件, 主体框)

<template>
<div class="demo">
    <h1>案例</h1>
    <h2>利用组件来实现动态显示框的传值</h2>
    <div style="text-align:left;margin-bottom:10px">
        <input class="btn"
                type="button"
                value="新增用户"
                @click="addUser">
    </div>
    <table class="table">
        <tr>
            <th>姓名</th>
            <th>外号</th>
            <th>技能</th>
            <th>操作</th>
        </tr>
        <tr v-for="(user,index) of userList"
            :key="user.id">
            <td>{{user.name}}</td>
            <td>{{user.nickName}}</td>
            <td>
                <span v-for="(skill,skillIndex) of user.skill" :key="skillIndex" class="tag">{{skill}}</span>
            </td>
            <td>
                <a href="javascript:;"
                    @click="editUser(user,index)">编辑</a> |
                <a href="javascript:;"
                    @click="deleteUser(index)">删除</a>
            </td>
        </tr>
    </table>
    <edit-modal v-show="isShow"
    :data="editedUser"
    @on-submit="submit"
    @on-cancel="cancel"></edit-modal>

</div>
</template>
<script>
import EditModal from '../components/model'
export default {
  name: 'demo14',
  data () {
    return {
      isShow: false,
      editedUser: {},
      editedUserIndex: -1,
      userList: [
        {
          id: 1562725945741,
          name: '欧阳锋',
          nickName: '西毒、老毒物',
          skill: ['蛤蟆功', '灵蛇杖法']
        },
        {
          id: 1562723132751,
          name: '洪七公',
          nickName: '北丐、老叫花',
          skill: ['降龙十八掌', '打狗棒法']
        },
        {
          id: 1562725939582,
          name: '黄药师',
          nickName: '东邪、黄老邪',
          skill: ['弹指神通', '碧海潮生曲']
        },
        {
          id: 1562725920190,
          name: '段智兴',
          nickName: '南帝、一灯大师',
          skill: ['一阳指', '先天功']
        }
      ]
    }
  },

  methods: {
    addUser () {
      this.isShow = true
    },
    editUser (user, index) {
      this.isShow = true
      this.editedUser = { ...user }
      this.editedUserIndex = index
    },
    deleteUser (index) {
      if (window.confirm('是否确认删除?')) {
        this.userList.splice(index, 1)
      }
    },
    submit (data) {
      console.log(data)
      if (this.editedUserIndex === -1) {
        // ADD
        data = {
          ...data,
          id: Date.now()
        }
        this.userList.unshift(data)
      } else {
        // EDIT
        this.userList.splice(this.editedUserIndex, 1, data)
      }
      this.cancel()
    },
    cancel () {
      this.isShow = false
      this.editedUser = {}
      this.editedUserIndex = -1
    }
  },
  components: {
    EditModal
  }
}
</script>
<style lang="less" scoped>
.title {
  font-size: 32px;
  color: blue;
}
.btn {
  border: none;
  height: 32px;
  line-height: 32px;
  padding: 0 16px;
  border-radius: 16px;
  cursor: pointer;
  outline: none;
  &.btn-blue {
    color: #fff;
    background: #00f;
  }
  &.btn-gray {
    color: #333;
    background: #e0e0e0;
  }
}

.table {
  width: 100%;
  border-collapse: collapse;
  th {
    background: #eee;
  }
  th,
  td {
    padding: 8px 0;
    border: 1px solid #ccc;
  }
}
.tag {
  display: inline-block;
  padding: 0 8px;
  line-height: 1.5;
  background: #f0f0f0;
  //   background: grey;
  border: 1px solid #d0d0d0;
  border-radius: 4px;
  margin: 4px;
}
</style>

components/model.vue部分(子组件,动态显示框)

<template>

    <div class="modal"
         v-show="isShow">
        <form class="form">
            <label class="form-item">
                <span class="label-text">姓名:</span>
                <input type="text"
                        v-model="editedUser.name"
                        class="form-input">
            </label>
            <label class="form-item">
                <span class="label-text">外号:</span>
                <input type="text"
                        v-model="editedUser.nickName"
                        class="form-input">
            </label>
            <label class="form-item">
                <span class="label-text">技能:</span>
                <textarea v-model="skill"
                        placeholder="多个技能之间用回车隔开"
                         rows="4"
                         class="form-input textarea"></textarea>
            </label>
            <div class="form-item text-center">
                <input type="button" class="btn btn-blue" value="提交" @click="submit">
                <input type="button" class="btn btn-gray" value="取消" @click="cancel">
            </div>
        </form>
    </div>

</template>
<script>
export default {
  name: 'model',
  data () {
    return {
      isShow: false,
      editedUser: this.data
    }
  },
  props: {
    data: {
      type: Object,
      // eslint-disable-next-line vue/require-valid-default-prop
      default: {}
    }
  },
  computed: {
    skill: {
      get () {
        return this.editedUser.skill ? this.editedUser.skill.join('\n') : ''
      },
      set (val) {
        let skill = val.split('\n')
        this.editedUser = {
          ...this.editedUser,
          skill
        }
        console.log(this.editedUser)
      }
    }
  },
  methods: {
    submit () {
      const { name, nickName, skill } = this.editedUser
      if (!name) {
        alert('请输入姓名')
        return
      } else if (!nickName) {
        alert('请输入外号')
        return
      } else if (!skill || !skill.join('')) {
        alert('请输入技能')
        return
      }
      this.$emit('on-submit', this.editedUser)
    },
    cancel () {
      this.$emit('on-cancel')
    }
  },
  watch: {
    data (val) {
      this.editedUser = val
    }
  }
}
</script>
<style lang="less" scoped>
.modal {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  &:before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.6);
  }
  .form {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    padding: 16px;
    border-radius: 8px;
    background: #fff;
  }
  .form-item {
    display: block;
    text-align: left;
    margin-top: 10px;
    &.text-center {
      text-align: center;
    }
    .label-text {
      margin-right: 8px;
      line-height: 32px;
      font-size: 14px;
    }
    .form-input {
      width: 240px;
      padding: 0 8px;
      background: #fff;
      border: 1px solid #d0d0d0;
      border-radius: 4px;
      height: 32px;
      line-height: 1.8;
      //   font-size: 14px;
      //   vertical-align: top;
      &.textarea {
        height: 80px;
        overflow: hidden;
        vertical-align: top;
        height: auto;
      }
    }
    // .btn {
    //   margin: 0 4xp;
    // }
  }
}

.btn {
  border: none;
  height: 32px;
  line-height: 32px;
  padding: 0 16px;
  border-radius: 16px;
  cursor: pointer;
  outline: none;
  &.btn-blue {
    color: #fff;
    background: #00f;
  }
  &.btn-gray {
    color: #333;
    background: #e0e0e0;
  }
}
</style>

结果:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

------------------------结束分割线----------------------------------

发布了18 篇原创文章 · 获赞 4 · 访问量 2218

猜你喜欢

转载自blog.csdn.net/qq_41996454/article/details/104062225