在本文中, 我主要寫寫$emit的一些用法和實例(筆記用)
1.用法$emit( eventName, […args] )
eventName:一個事件名,會綁定一個方法。當組件觸發事件後,將調用這個方法。 …args:附加參數,會被拋出,由上述綁定的方法接收使用。文檔說:它是一個觸發當前實例上的事件。附加參數都會傳給監聽器回調。
子組件使用this.$emit()向父組件傳值。首先必須在父組件中引用子組件,然後實現傳值。
使用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>
<h1>案例</h1>
<h2>利用組件來實現動態顯示框的傳值</h2>
<div style="text-align:left;margin-bottom:10px">
<input
type="button"
value="新增用戶"
@click="addUser">
</div>
<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">{{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
v-show="isShow">
<form>
<label>
<span>姓名:</span>
<input type="text"
v-model="editedUser.name"
>
</label>
<label>
<span>外號:</span>
<input type="text"
v-model="editedUser.nickName"
>
</label>
<label>
<span>技能:</span>
<textarea v-model="skill"
placeholder="多個技能之間用回車隔開"
rows="4"
></textarea>
</label>
<div>
<input type="button" value="提交" @click="submit">
<input type="button" 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>結果:
在這裡插入圖片描述在這裡插入圖片描述----結束分割線----