Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

state 中的数据不能有小数点 #968

Closed
nyrf opened this issue Oct 30, 2018 · 14 comments
Closed

state 中的数据不能有小数点 #968

nyrf opened this issue Oct 30, 2018 · 14 comments
Assignees

Comments

@nyrf
Copy link

nyrf commented Oct 30, 2018

问题描述
想要实现打开页面,skuKeys根据skuDefault来设置选中项,如果选中,active 为true,加上class名为active。在skuKeys中,比如大小一项中,如果有如5.5这样带小数点的项,那么className={sku ${skuItems[item].active ? 'active' : '' } ${skuItems[item].disabled ? 'disabled' : '' } } 这句就无效了,只要改成没有小数点的名称,就没问题

复现步骤
[复现问题的步骤]

  1. skuKeys中大小中,比如5.5改成55,那就可以正常显示,只要有小数点,就会出错

[或者可以直接贴源代码,能贴文字就不要截图]

import Taro, { Component } from '@tarojs/taro'
import './index.scss'

class Demo extends Component {
  state = {
    skuKeys: {
      '颜色': {
       '红': {active: false, disabled: false, name: '红'},
       '黄': {active: false, disabled: false, name: '黄'}
      },
      '大小': {
        '5.5': {active: false, disabled: false, name: '5.5'},
        '45': {active: false, disabled: false, name: '45'}
      }
    },
    skuDefault: ['红', '5.5'],
    selectedSkus: {},
    skuSpecs: {},
    variants: {},
    selectedItem: {},
  }

  componentDidMount () {
    this.setDefault(this.state.skuKeys, this.state.skuDefault)
  }

  setDefault (ks, defaultsku) {
    const {skuKeys, skuDefault} = this.state
    let data = {}
    for (let i in skuKeys) {
      data[i] = skuKeys[i]
      for (let j in data[i]) {
        if (skuDefault.includes(j)) {
          data[i][j].active = true
        }
      }
    }
    this.setState({
      skuKeys: data
    })
  }

  render () {
    const {skuKeys} = this.state
    const skuList = Object.keys(skuKeys).map((key, index) => {
      const skuItems = skuKeys[key]
      const skuItemKeys = Object.keys(skuItems)
      return (
        <View className='item' key={index}>
           <View className="title">{key}</View>
           <View className='skus'>
             {
               skuItemKeys.map((item, idx) => {
                 return (
                  <View key={idx}
                        className={`sku ${skuItems[item].active ? 'active' : '' } ${skuItems[item].disabled ? 'disabled' : '' }` }
                  >
                    {skuItems[item].active}
                    {item}
                  </View>
                 )
               })
             }
           </View>
        </View>
      )
    })

    return (
      <View>
        {skuList}
      </View>
    )
  }
}
.item {
  display: flex;
 }
 .title {
  padding: 10px;
 }
.sku {
  border: 1px solid #ccc;
  padding: 10px;
  margin-right: 10px;
  // width: 60px;
  // height: 60px;
  line-height: 60px;
  text-align: center;
  font-size: 30px
}
.skus {
  display: flex;
  /*justify-content: space-around;*/
}
.active {
  color: white;
  background-color: red;
}
.disabled {
  /*color: #ddd;*/
  background-color: #ccc;
  border-color: #ccc;
  pointer-events: none;
}

期望行为
进入页面,skuDefault中的值默认选中,className加上active,比如 className='sku active'

报错信息

[这里请贴上你的完整报错截图或文字]
wx20181030-230813 2x

wx20181030-230758 2x

系统信息

  • 操作系统: osx 10.14
  • Taro 版本 1.1.0-beta.13
  • Node.js 版本 v10.5.0
  • 报错平台 weapp

补充信息
[可选]
[根据你的调查研究,出现这个问题的原因可能在哪里?]

@yuche yuche self-assigned this Oct 31, 2018
@nyrf
Copy link
Author

nyrf commented Oct 31, 2018

测试了其它符号,都可以,只有点不行,在小程序里用原生也没问题,好像是在转换后的问题

<block>
    <view>{{anonymousState__temp}}
        <view class="item" wx:key="{{index}}" wx:for="{{loopArray0}}"
        wx:for-item="key" wx:for-index="index">
            <view class="title">{{key.$original}}</view>
            <view class="skus">
            <view>{{key.$original}}</view>
                <view wx:key="{{idx}}" class="{{'sku ' + (key.skuItems[item].active ? 'active' : '') + ' ' + (key.skuItems[item].disabled ? 'disabled' : '')}}"
                wx:for="{{key.skuItemKeys}}" wx:for-item="item" wx:for-index="idx">
                {{item}}
                {{key['skuItems']['45'].active}}

                </view>
            </view>
        </view>
    </view>
</block>

小程序原生写法正常

<!--index.wxml-->
<view class="container">
 <view wx:for="{{skuKeys}}" wx:for-index="index" wx:for-item="key" class='item'>
   {{index}}
   <view class='skus'>
     <view wx:for="{{key}}" wx:for-index="idx" wx:for-item="item"
      class="{{'sku ' + (item.active ? 'active' : '')}}">
        {{item.name}} {{item.active}}
      </view>
   </view>
 </view>

</view>
//index.js
const app = getApp()

Page({
  data: {
    skuKeys: {
      '颜色': {
        '红': { active: false, disabled: false, name: '红' },
        '黄': { active: false, disabled: false, name: '黄' }
      },
      '大小': {
        '5.5': { active: false, disabled: false, name: '5.5' },
        '45': { active: false, disabled: false, name: '45' }
      }
    },
    skuDefault: ['红', '5.5'],
    selectedSkus: {},
    skuSpecs: {},
    variants: {},
    selectedItem: {}
  },

  setDefault() {
    const { skuKeys, skuDefault } = this.data
    let data = {}
    for (let i in skuKeys) {
      data[i] = skuKeys[i]
      for (let j in data[i]) {
        if (skuDefault.includes(j)) {
          data[i][j].active = true
        }
      }
    }
    this.setData({
      title: 'deng',
      skuKeys: data
    })
    console.log(this.data.skuKeys)
  },

  onLoad: function() {
    this.setDefault()
    console.log('ok');
  }
})

wx20181031-153323 2x

@yuche yuche added bug Something isn't working 编译器 labels Nov 1, 2018
@nyrf
Copy link
Author

nyrf commented Nov 6, 2018

@yuche 请问这个是哪里的原因?还有#886,这两个地方没办法,现在用原生写了这个部分,暂时解决了问题,谢谢

@yuche
Copy link
Contributor

yuche commented Nov 6, 2018

#886 你在循环中不要从 this.state 中拿数据,先给他起个名字不久可以了吗

@nyrf
Copy link
Author

nyrf commented Nov 6, 2018

更新了最新版,#912 这里提到的问题解决了,同样#886的问题可以先设置个名字再放进循环了。主要是这个key里有.不正确的问题了。

@nyrf
Copy link
Author

nyrf commented Nov 9, 2018

今晚发现我api获取的数据是正确的,不过传给props后,4.7这类就变成如下所示了,
wx20181109-234622 2x

@nyrf
Copy link
Author

nyrf commented Nov 13, 2018

@yuche 请问下这个问题现在有什么办法吗?因为项目里好多这种类型的,已经写了好几个原生组件了,主要是像4.7这类带小数点的object的key传给props时,被分解了。

@yuche
Copy link
Contributor

yuche commented Nov 13, 2018

初步判断是微信的问题。生成出来的 wxml 和数据应该都没有问题。
原生生成的数据是用对象来循环,taro 生成的是用数组来循环,当用数组时循环时可能就可能触发了微信模板的 bug。否则也不至于颜色可以,但大小不行。

image

@nyrf
Copy link
Author

nyrf commented Nov 13, 2018

@yuche 我把taro生成的loopArray0和wxml用原生的写了一次,是可以正常的

Page({
  data: {
    loopArray0: [{ "skuItems": { "红": { "active": true, "disabled": false, "name": "红" }, "黄": { "active": false, "disabled": false, "name": "黄" } }, "skuItemKeys": ["红", "黄"], "$original": "颜色" }, { "skuItems": { "45": { "active": false, "disabled": false, "name": "45" }, "5.5": { "active": true, "disabled": false, "name": "5.5" } }, "skuItemKeys": ["45", "5.5"], "$original": "大小" }]
  },

  onShow() {
    console.log(this.data.loopArray0)
  }
})

下面是直接用的taro生成的wxml

<block>
    <view>
        <view class="item" wx:key="{{index}}" wx:for="{{loopArray0}}" wx:for-item="key"
        wx:for-index="index">
            <view class="title">{{key.$original}}</view>
            <view class="skus">
                <view wx:key="{{idx}}" class="{{'sku ' + (key.skuItems[item].active ? 'active' : '') + ' ' + (key.skuItems[item].disabled ? 'disabled' : '')}}"
                wx:for="{{key.skuItemKeys}}" wx:for-item="item" wx:for-index="idx">{{key.skuItems[item].active}}{{item}}</view>
            </view>
        </view>
    </view>
</block>

wx20181113-193125 2x

@nyrf
Copy link
Author

nyrf commented Nov 13, 2018

这个是用tarojs写的生成的js,用 console.log('得到的state', this.__state)这句输出的结果是正确的,不过到了下面用Component(require('../../npm/@tarojs/taro-weapp/index.js').default.createComponent(Demo, true));后,数据就不正常了,我在这前面写了一句console.log('taro createComponent后生成的', com) ,看了下输出结果,一共输出三次得到的state,一次taro生成的,如图

wx20181113-195416 2x

然后解开看下
wx20181113-195759 2x
wx20181113-195816 2x

可以看出,taro createComponent在数据生成完成之前,不过具体为什么不带小数点就没问题我也不清楚了,而且如我上面这里#968 (comment) 写的,我从api得到数据,然后prop一个product的object过去,带小数点的key会被分解了。所以应该不是微信本身的问题

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _index = require("../../npm/@tarojs/taro-weapp/index.js");

var _index2 = _interopRequireDefault(_index);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var Demo = function (_BaseComponent) {
  _inherits(Demo, _BaseComponent);

  function Demo() {
    var _ref;

    var _temp, _this, _ret;

    _classCallCheck(this, Demo);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Demo.__proto__ || Object.getPrototypeOf(Demo)).call.apply(_ref, [this].concat(args))), _this), _this.$usedState = ["loopArray0", "$anonymousCallee__3", "skuKeys", "skuDefault", "selectedSkus", "skuSpecs", "variants", "selectedItem"], _this.state = {
      skuKeys: {
        '颜色': {
          '红': { active: false, disabled: false, name: '红' },
          '黄': { active: false, disabled: false, name: '黄' }
        },
        '大小': {
          '5.5': { active: false, disabled: false, name: '5.5' },
          '45': { active: false, disabled: false, name: '45' }
        }
      },
      skuDefault: ['红', '5.5'],
      selectedSkus: {},
      skuSpecs: {},
      variants: {},
      selectedItem: {}
    }, _this.$$refs = [], _temp), _possibleConstructorReturn(_this, _ret);
  }

  _createClass(Demo, [{
    key: "_constructor",
    value: function _constructor(props) {
      _get(Demo.prototype.__proto__ || Object.getPrototypeOf(Demo.prototype), "_constructor", this).call(this, props);
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      this.setDefault(this.state.skuKeys, this.state.skuDefault);
    }
  }, {
    key: "setDefault",
    value: function setDefault(ks, defaultsku) {
      var _state = this.state,
          skuKeys = _state.skuKeys,
          skuDefault = _state.skuDefault;

      var data = {};
      for (var i in skuKeys) {
        data[i] = skuKeys[i];
        for (var j in data[i]) {
          if (skuDefault.includes(j)) {
            data[i][j].active = true;
          }
        }
      }
      this.setState({
        skuKeys: data
      });
    }
  }, {
    key: "_createData",
    value: function _createData() {
      this.__state = arguments[0] || this.state || {};
      this.__props = arguments[1] || this.props || {};
      ;

      var skuKeys = this.__state.skuKeys;


      var $anonymousCallee__3 = Object.keys(skuKeys);
      var loopArray0 = Object.keys(skuKeys).map(function (key, index) {
        key = {
          $original: (0, _index.internal_get_original)(key)
        };

        var skuItems = skuKeys[key.$original];
        var skuItemKeys = Object.keys(skuItems);
        return {
          skuItems: skuItems,
          skuItemKeys: skuItemKeys,
          $original: key.$original
        };
      });
      Object.assign(this.__state, {
        loopArray0: loopArray0,
        $anonymousCallee__3: $anonymousCallee__3
      });
      console.log('得到的state', this.__state)
      return this.__state;
    }
  }]);


  return Demo;
}(_index.Component);

Demo.properties = {};
Demo.$$events = [];
exports.default = Demo;

const com = require('../../npm/@tarojs/taro-weapp/index.js').default.createComponent(Demo, true)
console.log('taro createComponent后生成的', com)
Component(com);

@yuche
Copy link
Contributor

yuche commented Nov 14, 2018

原因在于 Taro 的 setState 会帮你自动 diff 数据,然后用路径的形式最小化更新。形如 loopArray0.skuItems.4.5.active 这样的形式小程序无法识别,所以就导致了这个 bug。

你可以暂时用 this.$scope.setData 来更新你的数据避免这个问题.

@nyrf
Copy link
Author

nyrf commented Nov 14, 2018

谢谢,原来如此,我现在有小数点的组件都用原生写了,后面用 this.$scope.setData 试下,这个问题还有希望处理么?

@yuche
Copy link
Contributor

yuche commented Nov 14, 2018

我们会和微信小程序开发组沟通尝试去解决这个问题

@nyrf
Copy link
Author

nyrf commented Nov 14, 2018

好的,谢谢

@yuche yuche changed the title 动态设置className时,使用map循环,如果key里有带小数点,会设置出错 state 中的数据不能有小数点 Nov 22, 2018
@yuche yuche added 微信小程序自身限制 and removed bug Something isn't working 编译器 labels Nov 22, 2018
@yuche yuche closed this as completed Jan 7, 2019
@nyrf
Copy link
Author

nyrf commented Jan 9, 2019

@yuche 你好,请问这个现在可以了?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants