b 0
,
r 18
,
❤ 正在询问中

6 月

  • pubdate:2020-06-02 12:50:46
  • tags:每日总结

2020-6-2

VueX 与 ts 的结合进阶

写出来这个功能之后,虽然回头看很简单。但我好像得到了某种升华,不仅仅是这段代码进阶了,我能感觉到我也进阶了

import Vue from "vue";
import Vuex from "vuex";
import { API } from "@/services/mods";
import { debounce } from "@/util/util_fun";
import { config } from "@/config";
Vue.use(Vuex);
/** __开头的属性是不会保存到store 的 */
const _state = {
  user_info: {} as typeof API.报表开发移动端.postCustomerInfoValidateLogin.init["data"],
  wxUsers: {} as un_return_promise<typeof API.报表开发移动端.postCustomerInfoFindCustomerInfoList.request>["data"],
  /** 日报的缓存 */
  daily_cache: {},
  /** [这里进去的时候会查询这个缓存](src\pages\mine\view_subordinate_schedule\_view_subordinate_schedule_list.ts) */
  查看下级选人缓存: [] as string[],
  /** 当前选择的日程展示方式
   *
   * **副作用** 会设置tabBar index为1的按钮的text为当前值
   */
  scheduleType: "日程" as "日程" | "周程" | "月程",
  /** 当前选中的tab地址 */
  __tabPath: "",
  __1: "测试存储",
};

const cache_state = uni.getStorageSync("state");
Object.assign(_state, cache_state);
type mutations_key = keyof typeof mutations;

/**
 * **注意** 这里的 mutations 里面的函数入参和vuex的要求是颠倒的,
 * 原因是为了 commit.set_packet_token 这样的方法可以直接跳转过来,
 * 在store_options中我是包了一层函数将参数调转位置交给这里面的函数
 *
 * **最后一个 state 参数不应该传入**
 * */
const mutations = {
  set_user_info(user_info: typeof _state.user_info, state = _state) {
    state.user_info = user_info;
  },
  set_packet_token(packet_token: string, state = _state) {
    state.user_info.packet_token = packet_token;
  },
  set_wxUsersVoList(wxUsers: typeof _state.wxUsers, state = _state) {
    state.wxUsers = wxUsers;
  },
  set_daily_cache(daily_cache: typeof _state.daily_cache, state = _state) {
    state.daily_cache = daily_cache;
  },
  /** **jsdoc注释测试** */
  set_查看下级选人缓存(查看下级选人缓存: typeof _state.查看下级选人缓存, state = _state) {
    state.查看下级选人缓存 = 查看下级选人缓存;
  },
  set_tabPath(tabPath: typeof _state.__tabPath, state = _state) {
    state.__tabPath = tabPath;
  },

  set_scheduleType(scheduleType: typeof _state.scheduleType, state = _state) {
    state.scheduleType = scheduleType;
  },
};
const store_options = {
  state: {} as typeof _state,
  mutations: (() => {
    var obj = {} as any;
    for (const key in mutations) {
      const f = mutations[key as keyof typeof mutations];
      /** 倒置入参,使参数顺序实际为正常 */
      obj[key] = function (state: any, ...payload: any[]) {
        //@ts-ignore
        return f(...payload, state);
      };
    }
    return obj;
  })(),
};

export const store = new Vuex.Store(store_options);

store.watch(
  (state) => {
    return state.scheduleType;
  },
  (scheduleType) => {
    uni.setTabBarItem({
      index: 1,
      text: scheduleType,
    });
    $emit_event("日程切换", scheduleType);
  },
);
/** 在这里使用 replaceState 而非直接在 store_options 赋值的原因是为了store.watch第一次加载的时候也可以生效 */
store.replaceState(_state);
/** vuex 的commit */
export const commit = {} as typeof mutations;

for (const key in store_options.mutations) {
  commit[key as mutations_key] = (data: any) => {
    return store.commit(key, data);
  };
}

/** 存储 store */
store.subscribe(
  debounce((mutation: any, state: any) => {
    if (config.isDev) {
      console.log(state);
    }
    const data = JSON.parse(JSON.stringify(state));
    for (const key in data) {
      /** 剔除 __ 开头的属性,这种属性不用存储 */
      if (data.hasOwnProperty(key) && key.startsWith("__")) {
        delete data[key];
      }
    }
    uni.setStorage({ key: "state", data: data });
  }, 200),
);

2020-6-4

sapper-postcss-tailwind-rollup

发现了这个结合了 tailwind 的 sapper 模板项目,并用它搭建了一个公司内的 ssr 服务

2020-6-5

node-tenpay

这是一个 node 的微信支付相关的库,用起来很不错,今天很简单的利用它搭建了一个支付的服务

核心代码如下,一开始我还只用了 api.unifiedOrder 返回的结果作为参数去调用微信的支付服务,结果不对。仔细看了下文档发现应当使用 api.getPayParamsByPrepay 来构造请求的参数

let result_unifiedOrder = await api.unifiedOrder({
  out_trade_no: Date.now() + "",
  body: "测试统一下单",
  /** 订单金额(分) */
  total_fee: "1",
  openid: "or_wc5NwKRewBjZE9hRmYVj1aFto",
});
let result_PayParams = await api.getPayParamsByPrepay({
  prepay_id: result_unifiedOrder.prepay_id,
});
const result = { result_unifiedOrder, result_PayParams };

2020-6-6

ansi_up

这个库可以将 ansi 转为 HTML ,另外写了一个小脚本,用于将 jenkins 中的输出利用这个库转为 HTML,看起来舒服多了

parcel CSS in js

我在写油猴脚本时经常有加载 CSS 的需求,这时利用打包工具直接将 CSS 内联到 js 中就十分有用

但 parcel 对于这种情况目前 import '***.css' 是不会将 CSS 内联进去的,我从 https://github.com/parcel-bundler/parcel/issues/1370 找到了内联 CSS 的方法,虽然感觉并不优雅

var css = fs.readFileSync("./ansi_to_html/ansi_to_html.css", "utf-8"); // <-- The css reader
var style = document.createElement("style");
style.type = "text/css";
style.appendChild(document.createTextNode(css));

2020-6-11

疑似 uni-app bug

当计算属性返回 undefined 的时候视图不会更新,它能监听到计算属性的变化,但就是视图不更新

2020-6-18

uni-app 及微信小程序类的 showLoading 与 showToast 处理

这个问题的本质在于 呈现给用户的消息不能消失的太快,而 showLoading 与 showToast 有不能并存,而是会覆盖掉。

我一开始简单的将他俩放到队列中,一个个的来显示。但这种做法有问题,例如先将 showToast 加入队列然后将 showLoading 加入队列,再调用 hideLoading 由于还在执行 showToast 没到执行 showLoading 的时候,hideLoading 关了个寂寞。

接下来 showToast 执行完毕队列执行下一个任务 showLoading 。这就完蛋了,没人再去关闭 showLoading 了,的时候,hideLoading 提前调用了。我此时想将 hideLoading 加入队列,这就更不行了 showLoading 不会主动结束啊, hideLoading 加入队列后永远执行不到他。

此时着实卡了我一段时间,最后想到这个队列不能完全按照先进先出走, showLoading 的本质在于提示且阻碍用户操作,那么 showLoading 执行的时候 hideLoading 被加入队列应当立即执行 hideLoading ,也就是 如果当前执行的是 showLoading 且队列中有 hideLoading 就立马执行,这样就基本解决了问题,虽然 showLoading 会有机会一闪而过,但这是为了 showToast 的妥协,我没有想到更好的办法

export const toast与loading排队执行 = () => {
  type Queue_item = {
    type: string;
    run(): Promise<unknown>;
  };
  class Queue {
    list = [] as Queue_item[];
    cur = undefined as undefined | Queue_item;
    add(item: Queue_item) {
      this.list.push(item);
      console.log("add", item);

      this.run();
    }
    run() {
      if (this.cur === undefined && this.list.length) {
        this.cur = this.list.shift();
        console.log(11111, this.cur, this.list);
        this.cur.run().finally(() => {
          this.cur = undefined;
          this.run();
        });
      } else if (this.cur !== undefined) {
        /** 解决loading 一直阻塞的问题 */
        if (this.cur.type === "loading") {
          const h = this.list.find((el) => el.type === "hideLoading");
          if (h) {
            /** 剔除掉这个任务 */
            this.list = this.list.filter((el) => el !== h);
            h.run();
          }
        }
      }
    }
    constructor() {
      setInterval(
        /** 这里循环执行是为了,当loading 执行阻塞中能去寻找 hideLoading 任务执行以关闭当前的loading */ () => {
          this.run();
        },
        25,
      );
    }
  }
  const q = new Queue();
  const rawShowToast = uni.showToast;
  const rawShowLoading = uni.showLoading;
  let rawShowLoading_s = [] as Function[];
  const rawhideLoading = uni.hideLoading;
  uni.showToast = (p: any) => {
    return q.add({
      type: "toast",
      run() {
        return new Promise((s) => {
          console.log("执行toast------------------", p);

          rawShowToast({
            ...p,
            success: (r) => {
              p.success && p.success(r);
              setTimeout(() => {
                s();
              }, p.duration || 1500);
            },
            fail: (e) => {
              p.fail && p.fail(e);
              s();
            },
          });
        });
      },
    });
  };
  uni.showLoading = (p: any) => {
    return q.add({
      type: "loading",
      run() {
        return new Promise((s) => {
          rawShowLoading_s.push(s);
          rawShowLoading({
            ...p,
            success: (r) => {
              p.success && p.success(r);
              rawShowLoading_s.push(s);
            },
            fail: (e) => {
              p.fail && p.fail(e);
              s();
            },
          });
        });
      },
    });
  };
  uni.hideLoading = () => {
    return q.add({
      type: "hideLoading",
      run() {
        return new Promise((s) => {
          rawhideLoading();
          console.log("------------------hideLoading");
          rawShowLoading_s.forEach((s) => s());
          rawShowLoading_s = [];
          s();
        });
      },
    });
  };

  // uni.showLoading({ title: "111" });
  // setTimeout(() => {
  //   //  测试
  //   console.log(1111111111111111111111111);

  //   uni.showToast({ title: Date.now() + "" });
  //   uni.showLoading({ title: "loading" });

  //   uni.showToast({ title: Date.now() + "" });
  //   uni.showToast({ title: Date.now() + "" });
  //   uni.hideLoading();
  //   uni.showToast({ title: Date.now() + "" });

  //   uni.showToast({ title: Date.now() + "" });
  //   uni.showToast({ title: Date.now() + "" });
  //   uni.showToast({ title: Date.now() + "" });
  // }, 5000);
};

2020-6-19

微信小程序 image 底部间隙问题

2020-6-22

今日给博客加上了在线编辑功能和登录功能

净心神咒

太上台星,应变无停。驱邪缚魅,保命护身。智慧明净,心神安宁。三魂永久,魄无丧倾。急急如律令。(这句不要念出声)

2020-6-23

微信 cover-view 换行

首先单个的长单词默认是不换行的,需要设置 word-break: break-all; , 然后微信的 cover-view 中如果只有单个长单词设置了 word-break: break-all; 虽然能换行但 cover-view 不会自动调整高度,导致换行后的文本根本看不见,但 white-space:pre-wrap; 的换行 cover-view 却会自动调整高度。

所以我的思路就是在单个的长单词或者长数字后面影藏另外一个单词利用 white-space:pre-wrap; 换行来完整的展现出长单词,实例如下:

<cover-view
      class="fb npp-red"
      style="font-weight:bold;font-size:16px;white-space:pre-wrap;word-break: break-all;height:auto;overflow: visible;"
>
      ¥{{ count_cart_discounts.activityTotalAmount }} <cover-view style="color:transparent">1</cover-view>
</cover-view>

这里的 count_cart_discounts.activityTotalAmount 就有可能是一个长数值。结果出现了被截断显示不完整的 bug 通过后面隐藏的 <cover-view style="color:transparent">1</cover-view> 成功全部显示出来了

deno 阿里云 runTime

2020-6-24

CSS div 部分透明渐变

主要是利用 mask 的 alpha 遮罩具体实现思路见 https://svelte.dev/repl/030dba75e2a44384b53c5fe6f235d3f8?version=3.23.2

Chrome 系的目前好像并不支持,但手机上 iOS 和安卓基本能用。

遮罩的要求则是 当 mask-mode 为 alpha 的时候他会根据遮罩层对应点的透明度来决定元素该位置的透明度,所以只要遮罩层的透明度是渐变的那么这个 div 自然也是透明渐变的效果了

2020-6-30

一些图形库

jsplumb 主要用于图形连线

看起来比 jsplumb 要更全一些

by 崮生 from 崮生 • 一些随笔 🎨,欢迎 赞助本文
本文欢迎分享与聚合,全文转载未经授权( 联系我)不许可。