父子组件的相互通信

前一节已经讲过vuex如何实现优惠券的赠删改,本章就不再赘述了。如需查看请回到上一节

1.直接利用element-ui表格布局搭建问卷详情页面

这里与优惠券页面不同的是:点击问卷名称可以进去详情页面,与删除问卷操作在store.js中进行封装。

<template>
  <div class="wrapper">
      <header>
          <el-button size="small"
          icon="el-icon-circle-plus-outline" 
          @click="$router.push('/questionnaire/handle')">
          新增
          </el-button>
      </header>
      <el-table :data="questData">
        <el-table-column label="问卷名称">
          <template slot-scope="scope">
            <el-button type="text" @click="cellClick(scope.$index)">
              {{scope.row.name}}
            </el-button>
          </template>
        </el-table-column>
        <el-table-column prop="value" label="题目总数"></el-table-column>
        <el-table-column prop="date" label="创建时间"></el-table-column>
        <el-table-column fixed="right" label="操作" width="100">
            <template slot-scope="scope">
                <el-button @click="handleClick(scope.$index)" type="text" size="small">修改</el-button>
                <el-button @click="deleteClick(scope.$index)" type="text" size="small">删除</el-button>
            </template>
        </el-table-column>
      </el-table>
  </div>
</template>

<script>
export default {
  computed:{
    questData() {
      return this.$store.state.questData
    }
  },
  methods:{
    handleClick(row) {
      this.$router.push({path: '/questionnaire/handle', query: {index: row}});
    },
    deleteClick(row) {
      this.$store.commit('setData', {
        type: 'delete',
        class: 'questData',
        index: row
      })
    },
    cellClick(row) {
      this.$router.push({path: '/questionnaire/details', query: {index: row}});
    }
  },
}
</script>

2.store.js问卷改动,setData()函数中data参数中

type:为对数据具体操作类型(add增,handle改,delete删)

class:为需要操作的数组(couponData,questDat)

index: 要对数组中第几个元素进行操作

data: 新增的数据或者修改好的数据

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
    state: {
        couponData: [
            {
                name: '中秋浓情购',
                value: 100,
                date1: '2018-9-20',
                date2: '14:20'
            },
            {
                name: '国庆大优惠',
                value: 200,
                date1: '2018-9-25',
                date2: '14:20'
            },
            {
                name: '双11购物狂欢',
                value: 1000,
                date1: '2018-11-11',
                date2: '14:20'
            },
        ],
        questData: [
            {
                name: '如何有效保持身材',
                value: 3,
                date: '2018-11-1',
                questList: [
                    {
                        name: '锻炼方式',
                        type: 2,
                        answerList: []
                    }
                ]
            }
        ]
    },
    mutations: {
        setData(state, data) {
            switch (data.type) {
                case 'add':
                    state[data.class].push(data.data)
                    break;
                case 'handle':
                    state[data.class].splice(data.index, 1, data.data);
                    break;
                case 'delete':
                    state[data.class].splice(data.index, 1)
                default:
                    console.log('此函数未被定义 !')
                    break;
            }
        }
    }
})

3.新增问卷页面(利用父子组件传值)

最终页面显示如下,我们需要添加选项封装成一个组件

1)先实现添加选项子组件QuestionnaireAnswer.vue

<template>
      <el-form :model="ruleForm" ref="ruleFormChild" label-width="100px" class="demo-ruleFrom">
          <div class="form-add">
              <div class="answer-title">题目{{index + 1}}</div>
              <el-form-item label="问题名称" style="width:310px" prop="name"
              :rules="[{ required: true, message: '请输入题目名称', trigger: 'blur' }]" >
                  <el-input v-model="ruleForm.name"></el-input>
              </el-form-item>
              <el-form-item class="from-inline" label="答案方式">
                  <el-select v-model="ruleForm.type" placeholder="请选择答案方式">
                      <el-option label="单选" value="1"></el-option>
                      <el-option label="多选" value="2"></el-option>
                      <el-option label="问答" value="3"></el-option>
                  </el-select>
              </el-form-item>
               <el-button class="detal-button" type="primary" size="small" icon="el-icon-delete" @click="deleteAnswer">删除</el-button>
          </div>
      </el-form> 
</template>

<script>
export default {
    props: {
        ruleForm: Object,
        index: Number
    },
    methods:{
        deleteAnswer() {
            this.$emit("index", this.index)
        },
    },
}
</script>

当点击删除按钮时,我们需要告诉父级组件。幸好 Vue 实例提供了一个自定义事件的系统来解决这个问题。我们可以调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个事件:

this.$emit("index", this.index)

然后我们可以用 v-on 在在父组件中上监听这个事件,就像监听一个原生 DOM 事件一样:

 <app-answer ... @index="deleteFrom"></app-answer>

父组件QuestionnaireHandle.vue完整代码如下:

<template>
  <div class="wrapper">
    <div class="questHandle">
        <header>
            <el-form :model="ruleForm" ref="ruleForm" label-width="100px" class="demo-ruleForm">
                <div class="form-title">{{titText}}</div>
                <el-form-item class="inputWidth" label="问卷名称" prop="name"
                :rules="[{ required: true, message: '请输入问卷名称', trigger: 'blur' }]">
                    <el-input v-model="ruleForm.name"></el-input>
                    <span class="el-input-msg">(不能超过20个字)</span>
                </el-form-item>
            </el-form>
        </header>
        <div class="main">
            <app-answer v-for="(item,index) in ruleFormChild" :key="index" :index="index" :ruleForm="item" @index="deleteFrom"></app-answer>
            <el-button icon="el-icon-circle-plus-outline" @click="addAnswer">继续添加</el-button>
        </div>
    </div>
    <div style="text-align: center;">
        <el-button @click="submitForm">{{submitText}}</el-button>
        <el-button @click="$router.back(-1)">关闭</el-button>
    </div>
  </div>
</template>

<script>
import Answer from './QuestionnaireAnswer'
import {formatDate} from '../../tools/tools.js'
export default {
  components:{
      'app-answer': Answer
  },
  data(){
    return {
        titText: '新增问卷',
        submitText: '立即创建',
        ruleForm: {},
        ruleFormChild: [
            {
                name: '',
                type: '',
            }
        ],
    }
  },
  methods: {
    submitForm() {
       this.$refs['ruleForm'].validate((valid) => {
            if (valid) {
                let length = this.ruleFormChild.length;
                this.ruleForm.value = length;
                this.ruleForm.date = formatDate(new Date(), 'yyyy-mm-dd');
                this.ruleForm.questList = this.ruleFormChild;
                this.$store.commit('setData', {
                    type: 'add',
                    class: 'questData',
                    data: this.ruleForm
                })
                 this.$router.push('/questionnaire')
            }else {
                this.$message('请填写相应必填信息!!!');
            }
       })
    },
    addAnswer() {
        this.ruleFormChild.push({
            name: '',
            type: ''
        })
    },
    deleteFrom(index) {
        this.ruleFormChild.splice(index, 1);
    },
  },
}
</script>

这样就实现了父子组件的相互通信了!

猜你喜欢

转载自blog.csdn.net/djz917/article/details/83616358