分页: 3/273 第一页 上页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下页 最后页 [ 显示模式: 摘要 | 列表 ]
12月7
穿梭门: https://www.npmjs.com/package/vuex-persistedstate
[codes=c#]
// yarn add vuex-persistedstate
import createPersistedState from "vuex-persistedstate";


let store = new Vuex.Store({
    plugins:[
          createPersistedState({
            reducer:data=>{
                return{
                   // 天选之子,存在localstorage中,更多option参看文档
                    city:data.city
                }
            }
        })
    ],
    modules:{
        cinema,
        tabbar,
        city
    }
})
[/codes]
12月7
一, pinia介绍
Pinia 是 Vue.js 的轻量级状态管理库,最近很受欢迎。它使用 Vue 3 中的新反应系统来构建一个直观且完全类型化的状态管理库。
Pinia的成功可以归功于其管理存储数据的独特功能(可扩展性、存储模块组织、状态变化分组、多存储创建等)。

pinia优点:
符合直觉,易于学习
极轻, 仅有 1 KB
模块化设计,便于拆分状态
Pinia 没有 mutations,统一在 actions 中操作 state,通过this.xx 访问相应状态虽然可以直接操作 Store,但还是推荐在 actions 中操作,保证状态不被意外改变

store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction 辅助函数,这在 Vuex 中很常见
支持多个Store
支持 Vue devtools、SSR 和 webpack 代码拆分

pinia缺点:
不支持时间旅行和编辑等调试功能

yarn add pinia@next
[codes=c#]
// @ts-check
import { defineStore, acceptHMRUpdate } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore({
  id: 'cart',
  state: () => ({
    /** @type {string[]} */
    rawItems: [],
  }),
  getters: {
    /**
     * @returns {Array<{ name: string; amount: number }>}
     */
    items: (state) =>
      state.rawItems.reduce((items, item) => {
        const existingItem = items.find((it) => it.name === item)

        if (!existingItem) {
          items.push({ name: item, amount: 1 })
        } else {
          existingItem.amount++
        }

        return items
      }, []),
  },
  actions: {
    /**
     * Add item to the cart
     * @param {string} name
     */
    addItem(name) {
      this.rawItems.push(name)
    },

    /**
     * Remove item from the cart
     * @param {string} name
     */
    removeItem(name) {
      const i = this.rawItems.lastIndexOf(name)
      if (i > -1) this.rawItems.splice(i, 1)
    },

    async purchaseItems() {
      const user = useUserStore()
      if (!user.name) return

      console.log('Purchasing', this.items)
      const n = this.items.length
      this.rawItems = []

      return n
    },
  },
})

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useCartStore, import.meta.hot))
}

[/codes]
穿梭门:
https://pinia.esm.dev/
在线demo https://stackblitz.com/github/piniajs/example-vue-3-vite
12月3
vscode安装json2ts插件
搜索json2ts或
https://marketplace.visualstudio.com/items?itemName=eriklynd.json-tools

或在线https://apihelper.jccore.cn/jsontool

[codes=c#]
// 复制JSON到粘贴板,然后ctrl+alt+v
{
  "id": 1,
  "name": "111",
  "address": "11",
  "ext": {
    "phone":"13312121212",
    "mail":"xx@xx.com"
  }
}

// 生成的代码
export interface Ext {
  phone: string;
  mail: string;
}

export interface RootObject {
  id: number;
  name: string;
  address: string;
  ext: Ext;
}
[/codes]
点击在新窗口中浏览此图片
12月3
typescript中快速创建一个跟接口模型结构一样的对象。

vscode定义一个class implements 这个interface,然后再使用出new即可
点击在新窗口中浏览此图片
[codes=c#]
import { setgroups } from "process";

// Model
interface Ext {
  Address: string,
  Phone: Number,
}

export interface UserInfo {
  Id: number,
  Name: string,
  Ext: Ext,
}

// 生成的代码可以使用=赋值
export class UserInfoModel implements UserInfo {
  Id: number = NaN;
  Name: string = '';
  Ext: Ext = {
    Address: '',
    Phone: NaN
  };
}

// Use
setup() {
  const state reactive({
    userInfo: new UserInfoModel(),
  });
  return {
    state,
  }
}
[/codes]
12月2

VUE3双向绑定

17:22大前端 » vue.js  From: 本站原创
[codes=c#]
//testCp


//use testCp

[/codes]
12月1
https://github.com/midwayjs/midway

Midway 是一个适用于构建 Serverless 服务,传统应用、微服务,小程序后端的 Node.js 框架。

Midway 可以使用 Koa,Express 或 Egg.js 作为基础 Web 框架。它还提供了独立使用的基本解决方案,例如 Socket.io,GRPC,Dubbo.js 和 RabbitMQ 等。

此外,Midway 也适用于前端/全栈开发人员的 Node.js 无服务器框架。构建下一个十年的应用程序。可在 AWS,阿里云,腾讯云和传统 VM /容器上运行。与 React 和 Vue 轻松集成。
11月30
仅当 “module” 选项设置为 “esnext” 或 “system”,并且 “target” 选项设置为 “es2017” 或更高版本时,才允许使用顶级 “await” 表达式。ts(1378)
[codes=c#]
{
  "compileOnSave": true,
  "compilerOptions": {
    "moduleResolution": "node",
    "alwaysStrict": true,
    "charset": "utf8",
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "inlineSourceMap": true,
    "module": "esnext", // 修改 commonjs -- esnext
    "newLine": "lf",
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": false,
    "noImplicitThis": true,
    "noUnusedLocals": false,
    "outDir": "dist",
    "pretty": true,
    "skipLibCheck": true,
    "strict": true,
    "strictPropertyInitialization": false,
    "stripInternal": true,
    "importHelpers": true,
    "target": "ES2018"
  },
  "exclude": [
    "app/public",
    "app/views",
    "dist",
    "node_modules",
    "test"
  ]
}



[/codes]
11月30

如果你在 Chrome Dev Tools 控制台中输入 JSON.parse('{"taskid": 9007199254740993}') 运行结果返回的将会是 {taskid: 9007199254740992}。为什么 parse 后的数值会不一致?

双精度浮点数 IEEE 754

JavaScript 采用双精度浮点数( IEEE 754 标准)来表示它的 Number 类型。一个数字占用 64 bits 存储空间(这里的每一位都只能存放 0 或 1):

第一位 0 表示正值、1 表示负值;第 2- 12 位表示 2 的指数部分(可正可负);剩下的 52 个 bits 表示尾数部分,它的长度决定了数字的精度。
(1)sign×2exponent0x3ff×1.mantissa

如果我们将符号位和指数位共 12 个 bits 表示为 16 进制(4 个二进制 bits 1111 得到 1 个  16 进制的 f),那么它的取值范围为 [000, 7ff]。其中,规范约定当取值 7ff 时,可以表示无穷大或 NaN。

所以双精度浮点数能表示的最大 16 进制数为 0x7fef_ffff_ffff_ffff,转为十进制约为 1.79 ×10 的 308 次方。能表示的数的范围非常大,但受限于尾数的长度,能“精确”表示的数字并不多,我们来看看这个数到底是多少。

最大安全整数

从以上表示公式我们能看到,当指数部分只取 1 位,尾数部分取满 52 位时,可以精确表示出 JavaScript 里的整数,其 16 进制形式为 0x001f_ffff_ffff_ffff ,即 9007199254740991。

它等于 2 的 53 次方减 1,在 ES6 中,可以通过 Number.MAX_SAFE_INTEGER 引用到这个数值。

Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1  // true Number.MAX_SAFE_INTEGER === 0x001f_ffff_ffff_ffff   // true Number.MAX_SAFE_INTEGER === 9007199254740991     // true Number.MAX_SAFE_INTEGER === -Number.MIN_SAFE_INTEGER  // true

超过这个最大安全整数的运算,都可能因为发生进位溢出,造成精度丢失。

前后端大数传输方案

大数的运算和前后端传输是前端开发领域中的一个重要知识点。

本文开头提到的问题,源自于一个真实的项目案例,taskid 是 MySQL 数据库中的 bigint 类型字段。在 MySQL 中,一个 bigint 存储占用 8 Bytes 的空间,即 64 bits。当取值为无符号整型时,能表示的范围是 0 到 2 的 64 次方减 1,即 18446744073709551615。

当 taskid 取值在 (9007199254740991, 18446744073709551615]  之间时,后端程序(受语言特性和第三方库影响)通常能正确的执行 JSON 序列化操作,并通过 HTTP 接口返回给前端,而前端执行 JSON.parse 解码时,会因为语言本身的限制发生精度丢失,引发 bug。

大数转字符串类型

为了解决大数传递精度丢失的问题,常见的方案是“将大数转为字符串类型”。具体的做法如下:

后端程序先将大数转为 string 类型,再进行 JSON encode,传给前端。前端拿到数据后 decode 成 string 类型,直接展示。当需要大数运算时,将 string split 成多段安全整数字符串,每段单独转为 number 类型,在安全范围内计算完成后,再 join 成 string 类型进行展示。

一些第三方库(如 json-bigint)之所以能正确的处理大数 parse ,且不造成精度丢失,其实现原理也是类似。在拿到接口的 JSON 数据时,并不直接 JSON.parse,而是先将整块数据当作 text 字符串,将其中的大数以 string 类型进行存储和标记,再使用定制化的 JSON.parse。

类型语义丢失

我们知道前端往后端 POST 数据时,有两种常见的编码形式 application/x-www-form-urlencoded 和 application/json 。

当我们需要传递一个 number 类型的 id 给接口时,application/x-www-form-urlencoded 在 HTTP Request Body 中传输的是 id=1,而 application/json 的 Body 则是 {"id":1} 。我们之所以认为后者的语义更好,是因为后者能正确地反映出 id 的真实类型为 number。

而当这个 id 为 String 类型时,前者传输的依然是 id=1,后者则变为了 {"id":"1"}。对于后端程序来说,这层类型语义能让参数类型校验和计算更加准确和方便。

而如果前后端采用将“大数转为字符串”的方案,当 taskid 以 string 类型返回时,调用方将无法判断出它在业务和 DB 中到底是 char 字符类型存储的,还是 bigint 类型存储,导致类型语义丢失的情况发生。

类型语义有那么重要吗?这是另外一个话题了,但从 TypeScript 的发展趋势来看,为 JavaScript 加一个明确的类型,有很重大的意义。

ECMAScript 与 JSON 标准中的冲突

为了解决大数运算的问题,ECMAScript 标准中引入了 BigInt 类型(当前处于 Stage 3,且 Chrome 已经支持),通过在数字后面加一个 n,可以显式的声明一个 BigInt 类型对象,在进行运算时,将不再会发生精度丢失。

0x001f_ffff_ffff_ffffn + 2n === 9007199254740993n // true 2n**64n - 1n === 18446744073709551615n // true

在前端环境中,可以极其方便地进行大数运算。但这种做法,在进行 JSON 编解码时却遇到了大难题。

JSON 标准(IETF 7159)中定义了 JSON 支持的数据展示类型为 string、number、boolean、null 和这四个基础类型所组成的 object、array 结构。其他 JavaScript 类型在编解码时都会被静默消除或转换。

JSON.stringify({a:undefined, b: NaN, c: Symbol('c'), d:new Date(), e: new Set([1,2,3]), f:()=>{}})  // {"b":null,"d":"2019-07-31T10:21:47.848Z","e":{}}

从开发者的直观感受上,BigInt 作为 Number 类型的补充,应当在 JSON 标准中当作 Number 类型被支持。但从语言设计的角度来看,1 和 1n 是完全不同的对象类型,如果使用同一种表示方式,那么必然会发生“类型语义丢失”的现象。

更麻烦的地方在于,JSON 标准属于更广泛的标准,对 JSON 标准的改动,会影响到其他所有语言的实现,这可不是 JavaScript 弟弟能 hold 得住的。作为 ES 标准的制定者,TC39 委员会的大神们搁置了这个问题,而调皮的 Chrome 则在开发者试图 stringify 一个 BigInt 时,抛出了 Do not know how to serialize a BigInt 的异常。

事实上 JSON 标准中已经预料到,如果不设定 Number 的精度标准,可能会在不同系统传递数值时发生精度丢失的问题,所以也有建议开发者按照双精度浮点数规范来约束自己的系统。

如何利用 JavaScript BigInt 类型在不造成类型语义丢失的前提下,解决前后端接口大数的传输,是一个既有趣又有挑战的话题,同时也相当考验标准制定者和开发者的智慧了。

11月29
在掘金上来的,保有版权,markdown格式
下载文件 (已下载 94 次)
11月26

Dockerfile

09:20软件分析与设计  From: 本站原创
分页: 3/273 第一页 上页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下页 最后页 [ 显示模式: 摘要 | 列表 ]