如何让 mixin 填充状态 ES6 模块?

How to make mixin populate state ES6 module?

_getUserProfile() 为 运行 并且宿主属性被填充后,使用 UserProfileMixin 的其他元素不会获得已填充的属性,它们只会变得未填充默认值。像 this.profile 将是 {} 而不是配置文件。

为什么会这样,我怎样才能让这个 mixin 从 mixin 中填充 es6 模块 user-profile-state.js

注意:对使用 Redux 不感兴趣,我对 ES6 模块作为状态管理很满意。仅在 Mixins 中存在问题。

% cat app/account/user-profile-state.js 
const profile = {};
let isLoggedIn = false;
let profilePic;

export {
  isLoggedIn,
  profile,
  profilePic,
};

% cat app/account/user-profile.js 
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import '@polymer/paper-button/paper-button.js';
import { PauseForRipple } from '../mixins/pause-for-ripple-mixin.js';
import { FetchMixins } from '../mixins/fetch-mixins.js';

import { HOST } from '../constants.js';
import { UserProfileMixin } from '../mixins/user-profile-mixin.js';

import {
  isLoggedIn,
  profile,
  profilePic,
} from '../account/user-profile-state.js';


class UserProfile extends UserProfileMixin(FetchMixins(PauseForRipple(PolymerElement))) {
  static get template() {
    return html`
      <style>
        :host {
          display: flex;
          align-items: center;
          justify-content: center;
          flex-direction: column;
          padding: 10px;
          height: 100%;
        }

        .login-text, .login-text-small {
          color: var(--primary-text);
          font-size: 25px;
          font-weight: 300;
        }

        .login-text-small {
          font-size: 15px;
        }

        --paper-input-container-color: red;

        .login-container {
          width: 250px;
          height: 100%;
          padding: 25px;
          display: flex;
          justify-content: center;
        }

        paper-material {
          height: 100%;
          border-radius: 2px;
        }

        paper-button {
          background-color: #fff;
          color: var(--button-text);
          width: 190px;
          font-size: 12px;
        }

        a {
          text-decoration: none;
        }
      </style>

      <div>First Name: [[profilePic]]</div>

    `;
  }

    static get properties() {
      return {
        isLoggedIn: {
          type: Boolean,
          value: isLoggedIn,
        },

        profile: {
          type: Object,
          value: profile,
        },

        profilePic: {
          type: String,
          value: profilePic,
        },

      };
    }


  ready() {
    super.ready();
    console.log(this.profile);
    console.log(this.isLoggedIn);
  }

}

% cat app/mixins/user-profile-mixin.js 
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
import { USER_PROFILE } from '../constants'; // host url
import {
  isLoggedIn,
  profile,
  profilePic,
} from '../account/user-profile-state.js';

let rawUserProfileMixin = (base) => {
  class foo extends base {
    constructor() {
      super();
    }

    static get properties() {
      return {
        // this is for host url
        USER_PROFILE: {
          type: String,
          value: USER_PROFILE,
        },

        isLoggedIn: {
          type: Boolean,
          value: isLoggedIn,
        },

        profile: {
          type: Object,
          value: profile,
        },

        profilePic: {
          type: String,
          value: profilePic,
        },

      };
    }

    _getUserProfile() {
      var url = `${this.HOST}${this.USER_PROFILE}`;
      var request = this.createRequest(url);

      fetch(request)
        .then(this.fetchError)
        .then(this.json)
        .then((response) => {
          if (response.profile) {
            console.log('aaa');
            this.isLoggedIn = true;
            this.profilePic = response.profile.pic;
            this.profile = Object.assign({}, response.profile);
          }
        })
        .catch((e) => {
          this.isLoggedIn = false;
          console.log('error in checking logged in mixin ' + e);
        });
    }

    ready() {
      super.ready();
    }
  }
  return foo;
};

export const UserProfileMixin = dedupingMixin(rawUserProfileMixin);

解决方案是制作访问器函数(参见 airbnb JS 样式指南)。

let profile = {};              
let isLoggedIn = false;
let profilePic;

const setProfile = (newValue) => {
  if (newValue) {
    profile = Object.assign({}, newValue);
    isLoggedIn = true;
    profilePic = profile.pic;
  } else {
    profile = null;
    isLoggedIn = false;
    profilePic = null;
  }
}

export {
  isLoggedIn,
  profile,
  profilePic,
  setProfile,
};

混音:

import {
  isLoggedIn,
  profile,
  profilePic,
  setProfile,
} from '../account/user-profile-state.js';


let rawUserProfileMixin = (base) => {
  class foo extends base {
    constructor() {
      super();
    }

    static get properties() {
      return {
        // this is for host url
        USER_PROFILE: {
          type: String,
          value: USER_PROFILE,
        },

        isLoggedIn: {
          type: Boolean,
          value: isLoggedIn,
        },

        profile: {
          type: Object,
          value: profile,
        },

        profilePic: {
          type: String,
          value: profilePic,
        },
      };
    }

    _getUserProfile() {
      var url = `${this.HOST}${this.USER_PROFILE}`;
      var request = this.createRequest(url);

      fetch(request)
        .then(this.fetchError)
        .then(this.json)
        .then((response) => {
          setProfile(response.profile);
        })
        .catch((e) => {
          this.isLoggedIn = false;
          console.log('error in checking logged in mixin ' + e);
        });
    }