父组件的data内容被子组件自动修改,请高人入内指点
发布于 3 年前 作者 feer 1405 次浏览 来自 问答
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

父级组件用了组件1,组件1引用了组件2,每当组件2给组件1返回值的时候,父组件里的lists被改变。

通过控制台打印如下图:

未改变的

被改变的

lists的被选中项中自动添加了组件2返回的token和avatar

下面是代码,请大神指点

父组件

<template>
  <div>
    <el-row :gutter="20">
      <el-col class="title-box" :span="24">
        <div class="title">
          <i class="el-icon-s-unfold"></i>
          账户设置 / 联系人
        </div>
        <div class="tip">这里是企业招聘联系人,你可以对其编辑、删除等操作。</div>
      </el-col>
    </el-row>
    <el-row :gutter="20">
      <el-col :span="12">
        <div class="box table">
          <div class="title-sen">负责人列表</div>
          {{lists}}
          <el-table border :data="lists" stripe style="width: 100%" v-loading="tableLoading">
            <el-table-column fixed="left" prop="name" label="姓名" width="120"></el-table-column>
            <el-table-column prop="phone" label="手机号" width="120"></el-table-column>
            <el-table-column prop="desc" label="备注" width="200"></el-table-column>
            <el-table-column fixed="right" label="操作" width="160">
              <template slot-scope="scope">
                <el-button @click="handleEdit(scope.row)" type="warning" size="mini" plain>编辑</el-button>
                <el-button
                  @click="handleDel(scope.row.id,scope.row.name)"
                  type="danger"
                  size="mini"
                  plain
                >作废</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-col>
      <el-col :span="12">
        <div class="box edit">
          <div class="title-sen">编辑负责人</div>
          <add-contact :pushData="pushData" @backValue="editSuccess"></add-contact>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import AddContact from "@/components/contact/add.vue";

export default {
  name: "list",
  components: {
    AddContact
  },
  data() {
    return {
      tableLoading: true,
      lists: [],
      pushData: {
        name: "",
        phone: "",
        desc: "",
        id: ""
      }
    };
  },
  watch: {
    pushData(e) {
      console.log("父级pushData变化");
      console.log(e);
      console.log(this.lists);
    },
    lists(e) {
      console.log("父级lists变化");
      console.log(e);
    }
  },
  created() {
    this.getList();
  },
  methods: {
    editSuccess() {
      this.getList();
    },
    getList() {
      this.tableLoading = true;
      this.$api.information.getContact().then(res => {
        this.tableLoading = false;
        this.lists = res;
      });
    },
    handleEdit(data) {
      console.log(this.lists);
      console.log("edit");
      console.log(data);
      this.pushData = data;
    },
    handleDel(id, name) {
      console.log(id);
      console.log(name);
    }
  },
  computed: {}
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.title-sen {
  padding: 10px 20px 30px;
  font-weight: 600;
}
</style>

子组件1

<template>
  <el-form :model="form" :rules="rules" ref="ruleForm" label-width="100px">
    <el-form-item label="姓名" prop="name">
      <el-input v-model="form.name" placeholder="请输入姓名"></el-input>
    </el-form-item>
    <el-form-item label="手机号" prop="phone">
      <el-input v-model="form.phone" placeholder="请输入手机号"></el-input>
    </el-form-item>
    <el-form-item label="备注" prop="desc">
      <el-input v-model="form.desc" placeholder="请输入"></el-input>
    </el-form-item>
    <el-form-item label="绑定微信" :error="wx_error">
      <qr-code v-if="!hasScan" action="bind" :size="100" @backData="backQrCodeData"></qr-code>
      <div v-else class="avatar" @click="handleChangeWx">
        <div class="bg">换绑</div>
        <el-avatar :size="90" :src="form.avatar"></el-avatar>
      </div>
    </el-form-item>
    <el-form-item>
      <el-button
        v-if="form.id != '0' && form.id !== '' && form.id !== undefined"
        type="warning"
        plain
        @click="submitForm('ruleForm')"
      >提交修改</el-button>
      <el-button v-else type="success" plain @click="submitForm('ruleForm')">确认新增</el-button>
      <el-button @click="resetForm()" plain>清空</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
import QrCode from "@/components/QrCode/index.vue";

export default {
  name: "contact_add",
  components: { QrCode },
  props: {
    pushData: Object
  },
  data() {
    return {
      form: this.pushData,
      hasScan: false,
      wx_error: "",
      rules: {
        name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
        phone: [
          { required: true, message: "请输入手机号", trigger: "blur" },
          { min: 11, max: 11, message: "请输入正确的手机号", trigger: "blur" }
        ]
      }
    };
  },
  watch: {
    pushData(val) {
      this.init(val);
    },
    form(e) {
      console.log("子form变化");
      console.log(e);
    }
  },
  methods: {
    init(val) {
      console.log("子组件初始");
      console.log(val);
      this.resetForm();
      this.form = val;
      if (this.form.avatar != "" && this.form.avatar !== undefined) {
        this.hasScan = true;
      }
    },
    // 更换微信
    handleChangeWx() {
      this.hasScan = false;
      this.form.token = "";
      this.form.avatar = "";
    },
    // 扫描二维码返回的token
    backQrCodeData(e) {
      console.log("back token.");
      this.hasScan = true;
      this.form.token = e.token;
      this.form.avatar = e.avatar;
    },
    // 提交表格
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          if (
            (this.form.avatar == "" || this.form.avatar == undefined) &&
            !this.form.token
          ) {
            this.wx_error = "请先绑定微信";
            return false;
          }
          this.$api.information.editContact(this.form).then(res => {
            this.$message.success("操作成功");
            this.$emit("backValue", res.id);
            this.resetForm();
          });
        } else {
          return false;
        }
      });
    },
    // 重置
    resetForm() {
      console.log("重置");
      this.hasScan = false;
      this.form = {
        id: "",
        name: "",
        phone: "",
        desc: ""
      };
    }
  }
};
</script>

<!-- 添加 scoped 使得style仅作用于本组件 -->
<style scoped>
.avatar {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  overflow: hidden;
  position: relative;
  cursor: pointer;
}
.avatar .bg {
  display: none;
  content: "点击更换";
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  background: rgba(0, 0, 0, 0.8);
  text-align: center;
  color: #ffffff;
  line-height: 100px;
}
.avatar:hover .bg {
  display: block;
}
</style>

子组件2

<template>
  <div
    class="qr-code"
    v-loading="codeLoading"
    v-bind:style="{width:size + 'px',height:size + 'px'}"
  >
    <div class="has-scan" v-if="hasScan && hasScanRes">
      <p class="icon">
        <i class="el-icon-success"></i>
      </p>
    </div>
    <div class="has-scan error" v-if="hasScan && !hasScanRes" @click="handleReload">
      <p class="icon">
        <i class="el-icon-warning"></i>
      </p>
      <p>扫描失败,点击刷新</p>
    </div>
    <img class="code-img" :src="codeImg" />
  </div>
</template>

<script>
export default {
  name: "QrCode",
  props: {
    action: String, // 获取二维码事件:bind 绑定,login 登录
    size: Number // 大小
  },
  data() {
    return {
      codeLoading: true,
      hasScan: false,
      hasScanRes: true,
      codeImg:
        "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQHl8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAySGRHX0ozcUVmXzMxcXNMNU51MVAAAgTcBkVeAwTAqAAA",
      socket: "" // websocket
    };
  },
  created() {
    //this.init();
    // 演示效果,生产环境删除
    console.log("code created.");
    setTimeout(() => {
      var d = new Date();
      console.log(d.getTime());
      this.$emit("backData", {
        token: "DwAAAA" + d.getTime(),
        avatar:
          "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
      });
    }, 3000);
  },
  methods: {
    handleReload() {
      this.codeLoading = true;
      this.open();
    },
    init: function() {
      if (typeof WebSocket === "undefined") {
        this.$alert(
          "您的浏览器版本过低,无法使用此功能!建议升级后再试。",
          "提示",
          {
            confirmButtonText: "知道了"
          }
        );
      } else {
        // 定义地址
        const url = "wss://";
        // 实例化socket
        this.socket = new WebSocket(url);
        // 监听socket连接
        this.socket.onopen = this.open;
        // 监听socket错误信息
        this.socket.onerror = this.error;
        // 监听socket消息
        this.socket.onmessage = this.getMessage;
      }
    },
    open: function() {
      console.log("socket连接成功");
      // 组合参数
      let data = {
        controller: "getCode",
        action: this.action
      };
      // 连接成功后发送参数
      this.send(data);
    },
    error: function() {
      console.log("连接错误");
    },
    getMessage: function(msg) {
      console.log(msg.data);
      let res = JSON.parse(msg.data); // 根据实际情况修改
      if (res.action == "backImg") {
        this.codeLoading = false;
        this.codeImg = res.img;
        return false;
      } else if (res.action == "hasScan") {
        this.hasScan = true;
        this.hasScanRes = res.scanRes;
        return false;
      } else if (res.action == "success") {
        this.$emit("backCallback", res.data);
        this.socket.close();
        return false;
      } else {
        return false;
      }
    },
    send: function(params) {
      this.socket.send(JSON.stringify(params));
    }
  }
};
</script>

<!-- 添加 scoped 使得style仅作用于本组件 -->
<style scoped>
.qr-code {
  display: inline-block;
  width: 100px;
  height: 100px;
  position: relative;
  padding: 5px;
  border: 1px solid #e8e8e6;
}
.has-scan {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.9);
  color: #06c242;
  display: flex;
  justify-content: center;
  align-content: center;
  flex-direction: column;
}
.has-scan.error {
  color: #f23009;
}
.has-scan p {
  width: 100%;
  margin: 0;
  padding: 0;
  text-align: center;
  font-size: 12px;
}
.has-scan .icon {
  font-size: 28px;
  line-height: 1.2;
}
.code-img {
  width: 100%;
  height: 100%;
}
</style>
回到顶部