select-show.gif

环境

使用element ui + lean cloud 纯前端使用,node run dev在localhost:8010运行

"dependencies": {
    "element-ui": "^1.4.2",
    "leancloud-storage": "^3.1.0",
    "leanengine": "^3.0.0",
    "vue": "^2.4.2",
    "vue-router": "^2.7.0"
  },

现象

点击下拉不回显,数据是能妥妥进存进数据库,当点击保存时,才出现select回显。而select的change事件也没有触发。

对比

使用node+express+leancloud作后端,没有这个问题

排查

尝试1. 升级vue/elementui版本,无果。

尝试2. 将select对应的字段使用AV数据表存储,而不是硬编码写在js中,也是一样。

尝试3. 将project对应给予初值,

project: {
        title: '新小区',
        style: '',
        layout: '',
        thumb: ''
      },
无果

尝试4. 使用projectObj.save(this.project),成功,是很不优雅,尤其在编辑修改时,诸如(this.project.title = project.title; this.project.style = project.style;),丧失对象特性,本可以project.save()解决的,不论project是新增还是修改。

<template>
  <el-card class="box-card">
    <div slot="header">
      <span>添加工程</span>
    </div>
    <el-form label-width="80px">
      <el-form-item label="标题" prop="title">
        <el-input v-model="project.title" @keyup.enter.native="save"></el-input>
      </el-form-item>
      <el-form-item label="风格" prop="style">
        <el-select v-model="project.style" placeholder="请选择" @change="change">
          <el-option v-for="item in style" :key="item" :label="item" :value="item">
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="户型" prop="layout">
        <el-select v-model="project.layout" placeholder="请选择">
          <el-option v-for="item in layout" :key="item" :label="item" :value="item">
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="save">添加</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>
<style>
</style>
<script>
export default {
  data() {
    return {
      project: {},
      style: ['现代', '简约', '中式', '欧式', '田园', '地中海'],
      layout: ['二居室', '三居室', '别墅', '店铺', '写字楼', '其他']
    }
  },
  created: function() {
    var AV = require('leancloud-storage');
    this.project = new AV.Object('Project');
  },
  methods: {
    change: function(value) {
      console.log(this.project.style);
      console.log('value', value);
    },
    save: function() {
      this.project.save().then((prj) => {
        this.$message({
          message: '保存成功',
          duration: 500
        });
      }, function(err) {
        console.log(err);
      })
    }
  }
}
</script>

另附原型声明

// 定义工程原型
var Project = AV.Object.extend('Project');
Object.defineProperty(Project.prototype,
  'title', {
    get: function() { return this.get('title'); },
    set: function (value) { this.set('title', value); }
  }
);
Object.defineProperty(Project.prototype,
  'style', {
    get: function() { return this.get('style'); },
    set: function (value) { this.set('style', value); }
  }
);
Object.defineProperty(Project.prototype,
  'layout', {
    get: function() { return this.get('layout'); },
    set: function (value) { this.set('layout', value); }
  }
);

这问题困扰了我2天了,希望能提供帮助,谢谢。

https://cn.vuejs.org/v2/api/index.html#data6

因为 vue 的数据监听的实现原理,vue 是需要使用 plain object 作为 data 的,因此并不推荐直接将 AV.Object 的实例作为 data。

在我们的 Demo 里,需要将 object 转成 plain object 之后再给 data 的: https://github.com/leancloud/leantodo-vue/blob/master/app.js#L17614

而在修改的时候,需要创建一个新的对象来进行修改的操作: https://github.com/leancloud/leantodo-vue/blob/master/app.js#L198-L20110

谢谢。

看了你给出的代码,利用.toJSON(),跟我的尝试4里的做法与你给的demo不谋而合的。

那么这就是目前为止,最优解罗~有点小不爽。因为在类型的都好好的没有异样,到了select却不灵了。双向绑定运行都正常的且存入数据库也都正常,却平白地多出一层对Bean的操作。

最后再贴上我的实现方式,希望没有理解错。

save: function() {
      // 测试当前数据信息
      console.log(this.project.layout);
      // return;
      this.loading = true;
      // 直接后leancloud提交
      var project = new this.AV.Object('Project');
      // this.project.save();
      if (this.isEdit) {
        project = this.projectObject;
      }
      project.save(this.project).then((prj) => {
        this.loading = false;
        this.$message({
          message: '保存成功',
          duration: 500
        });
        console.log(prj.get('title'));
      }, function(err) {
        this.loading = false;
        console.log(err);
      })
    }

编辑读取代码如下:

  created: function() {
    // 获取当前商品信息
    var projectId = this.$route.query.projectId;
    // console.log(projectId);
    if (projectId) {
      this.isEdit = true;
      var query = new this.AV.Query('Project');
      query.get(projectId).then(project => {
        this.project.title = project.title;
        this.project.style = project.style;
        this.project.layout = project.layout;
        this.project.thumb = project.thumb;
        this.projectObject = project;
      }, err => {
        console.log(err);
      });
    }
  }

其中project局部变量就是待操作的AV对象;this.project就是一个plain object;this.projectObject是读取到旧AV对象,等同与AV.Object.createWithoutData('Project', projectId);this.project.title = project.title是因为我已经defineProperty,等同于toJSON()。

刚刚又对get读取做了一点改进,通过delete移除objectId,createdAt,updatedAt后,再拷贝object,减少了对元素赋值的重复操作。

query.get(projectId).then(projectObject => {
        var project = projectObject.toJSON();
        delete project.objectId;
        delete project.createdAt;
        delete project.updatedAt;
        this._.extend(this.project, project);
        this.projectObject = projectObject;
      }, err => {
        console.log(err);
      });
1 人赞了这个帖子.