Giter VIP home page Giter VIP logo

westore's Issues

update方法缺乏回调功能

可以用将setData的方法promisify然后promise.all所有update产生的setData,但是可能对性能的影响较大。我改了以后会测一下,如果性能还行会发一个pull request。

组织自己的store可以使用这种方法

a.js

export default  {
    data: {
        numa: 1,
        numb: 2
    },
    getA() {
        console.log('a');
    }
}

b.js

export default  {
    data: {
        numc: 3,
        numd: 4
    },
    getA() {
        console.log('b');
    }
}

store.js

import a from './a.js'
import b from './b.js'

const commonData = {
    commona: 'common'
}
function storeMixin(options) {
    let result = {
        data: commonData ,
    }
    for (let k in options) {
        let value = options[k];
        if (value.data) {
            result.data[k] = value.data
            delete value.data
        }
        Object.assign(result, value)
    }
    return result;
}

export default storeMixin({a, b})

根据page划分store, 不过函数名字就不能重复了

关于globalData的一点问题

globalData如果不在组件和页面声明data依赖,在绑定视图初始显示会有问题,而且更改globalData的值时候还需要手动update()一次?

  this.store.data.globalPropTest = 'aaaa'
   this.update()

这种现象是正常现象吗?

原来的data 有一项 userInfo

我通过 store.data = new_data
new data 有一项 userInfo

通过update更新后
数据结构变成 这样

diff并没有把userInfo更新成空,而是把其中的每个属性都变成空了,我觉得这样逻辑是不对的,使用起来也有问题

新手有几个疑问😳

1、『Please using store.method to set method prop of data!』需要如何处理哈

我在组件里,如果没有设置pure:true 会出现这个提示,不知道有什么影响也不知道如何解决哈

2、还是不明白 pure:true的区别
我只明白,true的时候,data不会合并

仍可以修改this.store.data.xxx
却不能调用this.store.func(),调用某个store里的函数

3、组件里如果在lifetimesready生命周期的处理事件,不能够获取this.store的值
但是如果把ready拿到外面写就可以获取this.store

4、有一个很神奇的情况
页面获取数据,然后赋值
this.store.data["goodsList"] = [];
然后跳转到别的页面,在后退的时候,出现
image

但是如果使用setData就不会有这样情况

Update

这个情况,我发现复习场景是

页面A(有赋值data)=> redirectTo到页面B => redirectTo到页面A => 报错

但是如果是

页面A(有赋值data)=> navigateTo到页面B => redirectTo到页面A

就没问题

关于使用接口的更友好建议

我最近发现小程序es6转译支持 Proxy,那么可不可以用Proxy来代理 Page的data属性?
直接在onload函数中这样写

   this.data = new Proxy(this.data, {
                get: (target, key, proxy) => {
                    console.log("get")
                    return target[key]
                },
                set: (target, key, value, proxy) => {
                    this.update({
                        [key]: value
                    })
                    return Reflect.set(target, key, value, proxy)
                }
            })

so

this.msg= "hello"

就可以更新数据.而不用反复的调用发放,至于又没有什么问题 我暂时还没看

diff data 与 diff 页面疑问(存在即使 data 的值一样,但也要更新组件状态的情况)

我目前的理解是:无论是用 setdata 还是 update,最后在虚拟 dom 里面,都要把整个页面生成出来,再跟前一刻的状态来 diff,最后更新为新视图(react.js 是如此),所以即使 setdata diff 了一下,那些相同的数据被 pass,但最后是否都要重新 render 整个page 在虚拟 dom 里面??

还有一个很重要的问题是,这个很重要!!在表单组件里面,比如 switch 的 value 属性,即使每次 setdata 的时候,值是一样的,但都需要重新更新switch的状态的。场景是:switch 初始值为 true,用户手动改变了 switch 为 false,然后点击另外的按钮使得 switch 重置为默认 true,这个时候,在 this.update 来看,前后两次的值都为 true,就不会更新页面了

__nosuchmethod__类似需求没有被支持

var arr = [1,2,3];
observe(arr, function() {console.log("change")});
arr[3] = 2;
var obj = {a:1,b:2};
observe(obj, function() {console.log("change")});
obj.c = 3;

如果直接使用未定义的键的操作相关的监测事件未触发,如果在实际使用中要一直避免访问到未定义的键,那使用起来需很谨慎

polymer的observerjs通过暴露一个Platform.performMicrotaskCheckpoint()接口手动刷新,其余的方案采用定时器机制检查

希望改进的

希望再页面中可以 用this.data.my_info = xxx 的方式修改 而不是 this.store.data.myinfo
this.update == store.update ?在页面中使用哪个好 还是一样的

能否支持一些全局data及函数

使用场景:
例如用户信息(userInfo),信息这个基本上每个页面都用的到
而目前使用的是局部更新,就必须要在每个页面的data里再输入一次,有点繁琐

解决方案:
支持局部更新下
定义全局的data和函数

对象被添加了属性

对象会被加上了$observeProps、$observer属性,如何能使用只有原有的属性的对象
image

有一个疑问,就是当多个页面 每个页面使用到的data属性很多时,会不会很冗杂

举个栗子
pageA

Page({
  data: {
     a:1,
     b: 2,
     .....
    z: ''
  }
}) 

但是其实 只有 一两个属性是需要跨页面传输的(例如z),其他的都只是本页面使用,那么 如果这种情况 要采用westore 是不是必须所有属性都写到store (即使采用 分模块来加载,模块里面也都一一对应写好吧)

可能我表述的不是很清楚, 最终想表达的是 就是能不能只有写在store的属性时 才会被覆盖,其他的当前页面没有的,就不用覆盖。

在set和add函数中有无必要加入$observer.propertyChangedHandler的处理

var obj = {
  a: 1,
  b: 2
};
observe(obj, 'a', function (name, value, old) {
    console.log(name + "__" + value+"__"+old);
});
observe.set(obj, 'c', 2, true); // 并不会触发回调函数

解决方法:可将源码改成如下

    observe.set = function(obj, prop,value,exec) { 
        if(!exec){
            obj[prop] = value; 
        }
        var $observer = obj.$observer; 
        $observer.watch(obj, prop); 
        $observer.propertyChangedHandler.forEach(function(handler) {
            handler.eventPropArr.push(prop);
        })
        if(exec){
           obj[prop] = value;
        }
    };

不过这个有待商议哈

Array的重新赋值不会被捕捉到

以下不可行

var cache = [];
     observe(cache, function (name, value, old) {
            console.log(name + '__' + value + '__' + old);
        });
cache = [1]

这样可行:

var cache = {
      NoticeCache: []
}
observe(cache, function (name, value, old) {
            console.log(name + '__' + value + '__' + old);
        });

        cache.NoticeCache = [1, 2, 3];

observejs会触发多次事件

在使用observejs时为了跟原生的Object.observe 兼容,我写了如下代码

                objectObserve = Object.observe || function (obj, fun){
                        observe(obj, function (name, value, oldValue) {
                                fun && fun([{
                                    type: 'update',
                                    name: name,
                                    oldValue: oldValue
                                }]);
                        })
                    };

结果发现fun回调会被执行多次,目前我的办法是加一个定时器,100ms内只允许执行一次,这样可以解决多次触发的问题,但不太理解为什么会有触发多次的问题?

全页插件

使用westore-plugin中的两个文件create-plug.js,diff.js

在开发全页插件的时候,页面不能正常执行。尝试使用普通开发模式中的两个文件就可以正常运行。

而且我看示例中好几种模式的create.js/diff.js都不太一样,使用上有什么区别的?

有个疑问 关于页面data 和storejs 的data

页面声明了data但是没有用,一定要在storejs 声明data吗`//index.js
//获取应用实例
import store from '../../store'
import create from '../../utils/create'
var app = getApp()
const http = require('wehttp')
create(store,{
data: {
islogin: false,
offline: false,
remind: '加载中',

cores: [
  [{
    id: 'kb',
    name: '课表查询',
    disabled: false,
    teacher_disabled: false,
    offline_disabled: false
  },
    /**{ id: 'cj', name: '成绩查询', disabled: false, teacher_disabled: true, offline_disabled: false },
    { id: 'ks', name: '考试安排', disabled: false, teacher_disabled: false, offline_disabled: false },
    { id: 'kjs', name: '空教室', disabled: false, teacher_disabled: false, offline_disabled: true },
    { id: 'xs', name: '学生查询', disabled: false, teacher_disabled: false, offline_disabled: true },
    { id: 'ykt', name: '一卡通', disabled: false, teacher_disabled: false, offline_disabled: false },
    { id: 'jy', name: '借阅信息', disabled: false, teacher_disabled: false, offline_disabled: false },
    { id: 'xf', name: '学费信息', disabled: false, teacher_disabled: true, offline_disabled: false },
    { id: 'sdf', name: '电费查询', disabled: false, teacher_disabled: true, offline_disabled: false },
    { id: 'bx', name: '物业报修', disabled: false, teacher_disabled: false, offline_disabled: true }
  ],[
      /**{ id: 'cet', name: '四六级', disabled: false, teacher_disabled: true, offline_disabled: true},
    { id: 'fw', name: "志愿活动", disabled: false, teacher_disabled: true, offline_disabled: false}**/
  ]
],
card: {
  'kb': {
    show: false,
    time_list: [{
      begin: '8:00',
      end: '8:45'
    },
    {
      begin: '8:55',
      end: '9:40'
    },
    {
      begin: '10:05',
      end: '10:50'
    },
    {
      begin: '11:00',
      end: '11:45'
    },
    {
      begin: '14:00',
      end: '14:45'
    },
    {
      begin: '14:55',
      end: '15:40'
    },
    {
      begin: '16:05',
      end: '16:50'
    },
    {
      begin: '17:00',
      end: '17:45'
    },
    {
      begin: '19:00',
      end: '19:45'
    },
    {
      begin: '19:55',
      end: '20:40'
    },
    {
      begin: '20:50',
      end: '21:35'
    },
    {
      begin: '21:45',
      end: '22:30'
    }
    ],
    data: {}
  },
  'ykt': {
    show: false,
    data: {
      'last_time': '',
      'balance': 0,
      'cost_status': false,
      'today_cost': {
        value: [],
        total: 0
      }
    }
  },
  'jy': {
    show: false,
    data: {}
  },
  'sdf': {
    show: false,
    data: {
      'room': '',
      'record_time': '',
      'cost': 0,
      'spend': 0
    }
  }
},
user: {},
disabledItemTap: false //点击了不可用的页面

},
//分享
onShareAppMessage: function () {
return {
title: 'We重邮',
desc: '碎片化、一站式、一体化校园移动门户',
path: '/pages/index/index'
};
},
//下拉更新
onPullDownRefresh: function () {
if (app._user.is_bind) {
this.getCardData();
} else {
wx.stopPullDownRefresh();
}
},
checkbind(userID) {

},
onShow: function () {
//this.update()
//var that = this
//this.store.data.cores = {}
var _this = this;
var that = this;
// console.log("onshow")
var res = app.islogin()
if (res != false) {
that.setData({
islogin: true,
})

  //判断是否绑定
  res.then((res) => {
    console.log(res.data.is_bind)
    if (res.data.is_bind == false) {
      _this.setData({
        'remind': '未绑定',
      });
    } else {
      _this.setData({
        'remind': '加载中',
        student_ID: res.data.student_ID,
        student_Password: res.data.student_Password
      });
      //清空数据
      _this.setData({
        user: app.globalData.userinfo,
        'card.kb.show': false,
        'card.ykt.show': false,
        'card.jy.show': false,
        'card.sdf.show': false
      });
      _this.getCardData();
    }
  })
}
//离线模式重新登录
if (_this.data.offline) {
  _this.login();
  return false;
}

function isEmptyObject(obj) {
  for (var key in obj) {
    return false;
  }
  return true;
}

function isEqualObject(obj1, obj2) {
  if (JSON.stringify(obj1) != JSON.stringify(obj2)) {
    return false;
  }
  return true;
}
var l_user = _this.data.user, //本页用户数据
  g_user = app._user; //全局用户数据
//排除第一次加载页面的情况(全局用户数据未加载完整 或 本页用户数据与全局用户数据相等)
if (isEmptyObject(l_user) || !g_user.openid || isEqualObject(l_user.we, g_user.we)) {
  return false;
}
//全局用户数据和本页用户数据不一致时,重新获取卡片数据
if (!isEqualObject(l_user.we, g_user.we)) {
  //判断绑定状态
  if (!g_user.is_bind) {
    _this.setData({
      'remind': '未绑定'
    });
  } else {
    _this.setData({
      'remind': '加载中'
    });
    //清空数据
    _this.setData({
      user: app._user,
      'card.kb.show': false,
      'card.ykt.show': false,
      'card.jy.show': false,
      'card.sdf.show': false
    });
    _this.getCardData();
  }
}

},
onLoad: function () {
this.login();
if (this.data.user = {}) {
console.log("没登录")
}
},
userInfoHandler(data) {
var that = this
wx.BaaS.handleUserInfo(data).then(res => {
// res 包含用户完整信息,详见下方描述
that.setData({
islogin: true,
})
app.globalData.userinfo = res
console.log(res)
that.getCardData();
}, res => {
// res 有两种情况:用户拒绝授权,res 包含基本用户信息:id、openid、unionid;其他类型的错误,如网络断开、请求超时等,将返回 Error 对象(详情见下方注解)
})
},
login: function () {
var _this = this;
console.log(app.islogin())
//如果有缓存,则提前加载缓存
// 微信用户登录小程序

},
response: function (status) {
var _this = this;
if (status) {
if (status != '离线缓存模式') {
//错误
_this.setData({
'remind': status
});
return;
} else {
//离线缓存模式
_this.setData({
offline: true
});
}
}
_this.setData({
user: app._user
});
//判断绑定状态
if (!app._user.is_bind) {
_this.setData({
'remind': '未绑定'
});
} else {
_this.setData({
'remind': '加载中'
});
_this.getCardData();
}
},
disabled_item: function () {
var _this = this;
if (!_this.data.disabledItemTap) {
_this.setData({
disabledItemTap: true
});
setTimeout(function () {
_this.setData({
disabledItemTap: false
});
}, 2000);
}
},
//课表渲染
kbRender(info) {
if (info) {
var classlist = info
} else {
var classlist = wx.getStorageInfoSync('kb_today')
}

//console.log(classlist)
var _this = this
_this.setData({
  'card.kb.data': classlist,
  'card.kb.show': true,
  'card.kb.nothing': !classlist.length,
  'remind': ''
});

},
//获取当前时间
getCurrentWeekday() {
var myDate = new Date();
return myDate.getDay();
},
getCardData: function () {
var _this = this;
var student_ID = _this.data.student_ID
var student_Password = _this.data.student_Password
//判断并读取缓存

if (wx.getStorageSync('kb_today')) {
  _this.kbRender(wx.getStorageSync('kb_today'));
}
if (app.globalData.ykt) {
  yktRender(app.cache.ykt);
}
if (app.globalData.sdf) {
  sdfRender(app.cache.sdf);
}
if (app.globalData.jy) {
  jyRender(app.cache.jy);
}
if (_this.data.offline) {
  return;
}
// wx.showNavigationBarLoading();

http.request('https://coes-stud.must.edu.mo/coes/login.do', 'get', {
  'userid': student_ID,
  'password': student_Password
}, res => {
  console.log("res",res)
  http.request('https://coes-stud.must.edu.mo/coes/AcademicRecordsForm.do?intake=1809&formAction=Timetable', 'post', {
    'userid': student_ID,
    'password': student_Password
  }, {
    success: res => {
      console.log(res.statusCode)
      if (res.statusCode == 200) {
        var txt = res.data.toString()
        var info = ''
        var classlist = []
        var classlist_all = []
        var nowweek = _this.getCurrentWeekday()
        //str = '';
        var patt = /timetable\.add\('(\d+)',[\n\s]+'(\d+:\d+)',[\n\s]+'(\d+:\d+)',[\n\s]+'(\w+)',[\n\s]+'([^']+)',[\n\s]+'(\w+)',[\n\s]+'(\w+)',[\n\s]+'([^']+)',[\n\s]+'([^']+)'\+'\s+-\s+'\+[\n\s]+'([^']+)'\);/g;
        while (info = patt.exec(txt)) {
          console.log(info)
          var tempinfo = {
            "week": info[1],
            "when": info[2],
            "end": info[3],
            "what": info[5],
            "where": info[7]
          }
          classlist_all.push(info)
          if (tempinfo.week == nowweek) {
            classlist.push(tempinfo)
          }
        }
        //console.log(classlist)

        //保存课表缓存
        app.saveCache('kb', classlist_all);
        app.saveCache('kb_today', classlist);
        _this.kbRender(classlist);

      } else {
        //app.removeCache('kb');
      }
    }



      // _this.setData({ list: classlist})
      //_this.kbRender(classlist)
    })
})

//获取课表数据
//var kb_data = classlist
if (app._user.teacher) {
  kb_data.type = 'teacher';
}
/**var loadsum = 0; //正在请求连接数
loadsum++; //新增正在请求连接
wx.request({
  url: app._server + '/api/get_kebiao.php',
  method: 'POST',
  data: app.key(kb_data),

  complete: function() {
    loadsum--; //减少正在请求连接
    if (!loadsum) {
      if (_this.data.remind == '加载中') {
        _this.setData({
          remind: '首页暂无展示'
        });
      }
      wx.hideNavigationBarLoading();
      wx.stopPullDownRefresh();
    }
  }
});**/

/**一卡通渲染
function yktRender(list) {
  if (list.length > 0) {
    var last = list[0],
      last_time = last.time.split(' ')[0],
      now_time = app.util.formatTime(new Date()).split(' ')[0];
    //筛选并计算当日消费(一卡通数据有一定延迟,无法成功获取到今日数据,主页卡片通常不能展示)
    for (var i = 0, today_cost = [], cost_total = 0; i < list.length; i++) {
      if (list[i].time.split(' ')[0] == now_time && list[i].cost.indexOf('-') == 0) {
        var cost_value = Math.abs(parseInt(list[i].cost));
        today_cost.push(cost_value);
        cost_total += cost_value;
      }
    }
    if (today_cost.length) {
      _this.setData({
        'card.ykt.data.today_cost.value': today_cost,
        'card.ykt.data.today_cost.total': cost_total,
        'card.ykt.data.cost_status': true
      });
    }
    _this.setData({
      'card.ykt.data.last_time': last_time,
      'card.ykt.data.balance': parseFloat(last.balance),
      'card.ykt.show': true,
      'remind': ''
    });
  }
}
//获取一卡通数据
loadsum++; //新增正在请求连接
wx.request({
  url: app._server + '/api/get_yktcost.php',
  method: 'POST',
  data: app.key({
    yktID: app._user.we.ykth
  }),
  success: function(res) {
    if (res.data && res.data.status === 200) {
      var list = res.data.data;
      if (list) {
        //保存一卡通缓存
        app.saveCache('ykt', list);
        yktRender(list);
      }
    } else {
      app.removeCache('ykt');
    }
  },
  complete: function() {
    loadsum--; //减少正在请求连接
    if (!loadsum) {
      if (_this.data.remind) {
        _this.setData({
          remind: '首页暂无展示'
        });
      }
      wx.hideNavigationBarLoading();
      wx.stopPullDownRefresh();
    }
  }
});

//水电费渲染
function sdfRender(info) {
  _this.setData({
    'card.sdf.data.room': info.room.split('-').join('栋'),
    'card.sdf.data.record_time': info.record_time.split(' ')[0].split('/').join('-'),
    'card.sdf.data.cost': info.elec_cost,
    'card.sdf.data.spend': info.elec_spend,
    'card.sdf.show': true,
    'remind': ''
  });
}
if (!!app._user.we.room && !!app._user.we.build) {
  //获取水电费数据
  loadsum++; //新增正在请求连接
  wx.request({
    url: app._server + '/api/get_elec.php',
    method: 'POST',
    data: app.key({
      buildingNo: app._user.we.build,
      floor: app._user.we.room.slice(0, 1),
      room: parseInt(app._user.we.room.slice(1))
    }),
    success: function(res) {
      if (res.data && res.data.status === 200) {
        var info = res.data.data;
        if (info) {
          //保存水电费缓存
          app.saveCache('sdf', info);
          sdfRender(info);
        }
      } else {
        app.removeCache('sdf');
      }
    },
    complete: function() {
      loadsum--; //减少正在请求连接
      if (!loadsum) {
        if (_this.data.remind) {
          _this.setData({
            remind: '首页暂无展示'
          });
        }
        wx.hideNavigationBarLoading();
        wx.stopPullDownRefresh();
      }
    }
  });
}

//借阅信息渲染
function jyRender(info) {
  if (parseInt(info.books_num) && info.book_list && info.book_list.length) {
    var nowTime = new Date().getTime();
    info.book_list.map(function(e) {
      var oDate = e.yhrq.split('-'),
        oTime = new Date(oDate[0], oDate[1] - 1, oDate[2]).getTime();
      e.timing = parseInt((oTime - nowTime) / 1000 / 60 / 60 / 24);
      return e;
    });
    _this.setData({
      'card.jy.data': info,
      'card.jy.show': true,
      'remind': ''
    });
  }
}
//获取借阅信息
loadsum++; //新增正在请求连接
wx.request({
  url: app._server + "/api/get_books.php",
  method: 'POST',
  data: app.key({
    ykth: app._user.we.ykth
  }),
  success: function(res) {
    if (res.data && res.data.status === 200) {
      var info = res.data.data;
      if (info) {
        //保存借阅缓存
        app.saveCache('jy', info);
        jyRender(info);
      }
    } else {
      app.removeCache('jy');
    }
  },
  complete: function() {
    loadsum--; //减少正在请求连接
    if (!loadsum) {
      if (_this.data.remind) {
        _this.setData({
          remind: '首页暂无展示'
        });
      }
      wx.hideNavigationBarLoading();
      wx.stopPullDownRefresh();
    }
  }
});**/

}
});`

使用中遇到的不好的体验或者说是不足

1,在非页面,非组件内update store,store的数据只能同步到路由栈已存在的页面
2,打开新的页面 store的内容无法同步到新页面
关于问题出现的原因,create时候合并的data 是直接执行的,
那么在create执行之后,在页面被加入路由之前,这段时间的store的更新在 打开新页面的时候是无法相应更新的,这真的是很难受

Add demo gif to README

Disclaimer: This is a bot

It looks like your repo is trending. The github_trending_videos Instgram account automatically shows the demo gifs of trending repos in Github.

Your README doesn't seem to have any demo gifs. Add one and the next time the parser runs it will pick it up and post it on its Instagram feed. If you don't want to just close this issue we won't bother you again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.