返回顶部
首页 > 资讯 > 前端开发 > node.js >TypeScript在Model中的高级应用
  • 418
分享到

TypeScript在Model中的高级应用

2024-04-02 19:04:59 418人浏览 薄情痞子
摘要

这篇文章主要讲解了“typescript在Model中的高级应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“TypeScript在Model中的高级应用”

这篇文章主要讲解了“typescript在Model中的高级应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“TypeScript在Model中的高级应用”吧!

前言

mvc、MVVC等前端经典常用开发模式中,V、C往往是重头戏,可能是前端业务主要集中这两块。结合实际业务,笔者更喜欢路由模式、插件式设计,这种在迭代和维护上更能让开发者受益(不过你需要找PM协调这事,毕竟他们理解的简化用户体验,多半是怎么让用户操作简单)。但我们今天来看看Model,看看M有什么扩展的可能。

背景

在读到本文之前,你实际项目(如React+Redux)中请求服务器数据,可能是如下策略:

  1. componentDidMount 中发送redux action请求数据;

  2. 在action中发起异步网络请求,当然你已经对网络请求有一定封装;

  3. 在网络请求内部处理一定异常和边际逻辑,然后返回请求到的数据;

  4. 拿到数据this.setState刷新页面,同时可能存一份到全局redux中;

正常情况下,一个接口对应至少一个接口相应Model,万一你还定义了接口请求的Model、一个页面有5个接口呢?

如果项目已经引入TypeScript,结合编写Model,你的编写体验肯定会如行云流水般一气呵成!但实际开发中,你还需要对服务器返回的数据、页面间传递的参数等涉及到数据传递的地方,做一些数据额外工作:

  • 对null、undefined等空值的异常处理(在ES最新方案和TS支持里,新增:链式调用?和运算符??,请读者自行查询使用手册);

  • 对sex=0、1、2,time=1591509066等文案转义;

  • (还有其他吗?欢迎留言补充)

作为一个优秀且成熟的开发者,你肯定也已经做了上述额外的工作,在utils文件下编写了几十甚至上百的tool类函数,甚至还根据函数用途做了分类:时间类、年龄性别类、数字类、......,接着你在需要的地方import,然后你开始进行传参调用。是的,一切看上去都很完美!

上面这个流程说的就是笔者本人,:)。

现况

随着项目和业务的迭代,加上老板还是压时间,最坏的情况是你遇到了并没有遵守上述"开发规范"的同事,那结果只能是呵呵呵呵呵了。下面直接切入正题吧!

上述流程虽说有一定设计,但没有做到高内聚、低耦合的原则,个人觉得不利于项目后期迭代和局部重构。

推荐另一个设计原则:面向对象五大原则SOLID[3]

下面举个例子:

  • 接口里字段发生变更时,如性别从Sex改为Gender;

  • 前端内部重构,发现数据模型不匹配时,页面C支持从页面A附加参数a、或页面B附加参数b跳入,重构后页面B1附加参数b1也要跳转C。从设计来说肯定是让B1尽量按照以前B去适配时是最好的,否则C会越来越重。

上面提过不管是页面交互,还是业务交互,最根本根本是数据的交换传递,从而去影响页面和业务。数据就是串联页面和业务的核心,Model就是数据的表现形式。

再比如现在前后端分离的开发模式下,在需求确认后,开发需要做的第一件事是数据库设计和接口设计,简单的说就是字段的约定,然后在进行页面开发,最终进行接口调试和系统调试,一直到交付测试。这期间,后端需要执行接口单元测试、前端需要Mock数据开发页面。

如何解决

接口管理

目前笔记是通过JSON形式来进行接口管理,在项目初始化时,将配置的接口列表借助于 dva[4] 注册到Redux Action中,然后接口调用就直接发送Action即可。最终到拿到服务器响应的Data。

接口配置(对应下面第二版):

list: [   {     alias: 'getCode',     apiPath: '/user/v1/getCode',     auth: false,   },   {     alias: 'userLogin',     apiPath: '/user/v1/userLogin',     auth: false,     nextGeneral: 'saveUserInfo',   },   {     alias: 'loginTokenByJVerify',     apiPath: '/user/v1/jgLoginApi',     auth: false,     nextGeneral: 'saveUserInfo',   }, ]

第一版:

import { apiComm, apiMy } from 'services';  export default {   namespace: 'bill',   state: {},   reducers: {     updateState(state, { payload }) {       return { ...state, ...payload };     },   },   effects: {     *findBydoctorIdBill({ payload, callback }, { call }) {       const res = yield call(apiMy.findBydoctorIdBill, payload);       !apiComm.IsSuccess(res) && callback(res.data);     },     *findByDoctorIdDetail({ payload, callback }, { call }) {       const res = yield call(apiMy.findByDoctorIdDetail, payload);       !apiComm.IsSuccess(res) && callback(res.data);     },     *findStatementDetails({ payload, callback }, { call }) {       const res = yield call(apiMy.findStatementDetails, payload);       !apiComm.IsSuccess(res) && callback(res.data);     },   }, };

第二版使用高阶函数,同时支持服务器地址切换,减少冗余代码:

export const connectModelService = (cfg: any = {}) => {   const { apiBase = '', list = [] } = cfg;   const listEffect = {};   list.forEach(kAlias => {     const { alias, apiPath, nextGeneral, cbError = false, ...options } = kAlias;     const effectAlias = function* da({ payload = {}, nextPage, callback }, { call, put }) {       let apiBaseNew = apiBase;       // apiBaseNew = urlApi;       if (global.apiServer) {         apiBaseNew = global.apiServer.indexOf('xxx.com') !== -1 ? global.apiServer : apiBase;       } else if (!isDebug) {         apiBaseNew = urlApi;       }       const urlpath =         apiPath.indexOf('Http://') === -1 && apiPath.indexOf('https://') === -1 ? `${apiBaseNew}${apiPath}` : apiPath;       const res = yield call(hxRequest, urlpath, payload, options);       const next = nextPage || nextGeneral;       // console.log('=== hxRequest res', next, res);       if (next) {         yield put({           type: next,           payload,           res,           callback,         });       } else if (cbError) {         callback && callback(res);       } else {         hasNoError(res) && callback && callback(res.data);       }     };     listEffect[alias] = effectAlias;   });   return listEffect; };

上面看上去还不错,解决了接口地址管理、封装了接口请求,但自己还得处理返回Data里的异常数据。

另外的问题是,接口和对应的请求与相应的数据Model并没有对应起来,后面再次看代码需要一段时间才能梳理业务逻辑。

请读者思考一下上面的问题,然后继续往下看。

Model管理

一个接口必然对应唯一一个请求Model和唯一一个响应Model。对,没错!下面利用此机制进一步讨论。

所以通过响应Model去发起接口请求,在函数调用时也能利用请求Model判定入参合不合理,这样就把主角从接口切换到Model了。这里个人觉得优先响应Model比较合适,更能直接明白这次请求后拿到的数据格式。

下面先看看通过Model发起请求的代码:

SimpleModel.get(   { id: '1' },   { auth: false, onlyData: false }, ).then((data: ResponseData<SimpleModel>) =>   setTimeout(     () =>       console.log(         '设置返回全部数据,返回 ResponseData<T> 或 ResponseData<T[]>',         typeof data,         data,       ),     2000,   ), );

其中,SimpleModel是定义的响应Model,第一个参数是请求,第二个参数是请求配置项,接口地址被隐藏在SimpleModel内部了。

import { Record } from 'immutable';  import { ApiOptons } from './Common'; import { ServiceManager } from './Service';   const SimpleModelDefault = {   a: 'test string',   sex: 0, };  interface SimpleModelParams {   id: string; }  export class SimpleModel extends Record(SimpleModelDefault) {   static async get(params: SimpleModelParams, options?: ApiOptons) {     return await ServiceManager.get<SimpleModel>(       SimpleModel,       'http://localhost:3000/test',   // 被隐藏的接口地址       params,       options,     );   }    static sexMap = {     0: '保密',     1: '男',     2: '女',   };    sexText() {     return SimpleModel.sexMap[this.sex] ?? '保密';   } }

这里借助了immutable里的Record[5],目的是将jsON Object反序列化为Class Object,目的是提高Model在项目中相关函数的内聚。更多介绍请看我另外一篇文章:JavaScript的强语言之路&mdash;另类的JSON序列化与反序列化[6]

// utils/tool.tsx export const sexMap = {   0: '保密',   1: '男',   2: '女', };  export const sexText = (sex: number) => {   return sexMap[sex] ?? '保密'; };

直接在SimpleModel内部用this访问具体数据,比调用utils/tool函数时传入外部参数,更为内聚和方便维护。通过这种思路,相信你可以创造更多"黑魔法"的语法糖!

接着我们来看看 Common 文件内容:

 export class ResponseData<T = any> {   code? = 0;   message? = '操作成功';   toastId? = -1;   data?: T; }   export class ApiOptons {   headers?: any = {}; // 额外请求头   loading?: boolean = true; // 是否显示loading   loadingTime?: number = 2; // 显示loading时间   auth?: boolean = true; // 是否需要授权   onlyData?: boolean = true; // 只返回data }   export type ResultDataType<T> =   | T   | T[]   | ResponseData<T>   | ResponseData<T[]>   | ResponseData;

Service文件内部是封装了axiOS

import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; import { ApiOptons, ResponseData, ResultDataType } from './Common';   class Toast {   static loading(txt: string, time: number = 3) {     console.log(txt, time);     return 1;   }   static info(txt: string, time: number = 3) {     console.log(txt, time);     return 1;   }   static remove(toastId: number) {     console.log(toastId);   } }   const codeUnknownTask = -999;   export class InterfaceService {      private static userProfile: { sysToken?: '' } = {};   public static setUser(_user: any) {     InterfaceService.userProfile = _user;   }    constructor(props: ApiOptons) {     this.options = props;   }      public options = new ApiOptons();       public get sysToken(): string {     return InterfaceService.userProfile?.sysToken ?? '';   }       public get headers(): Object {     return {       Accept: 'application/json',       'Content-Type': 'application/json; charset=utf-8',       'app-info-key': 'xxx', // 自定义字段     };   }       preCheck() {     if (this.options.loading && this.options.loadingTime > 0) {       return Toast.loading('加载中...', this.options?.loadingTime ?? 3);     }     return -1;   }       public static async getJSON(url: string) {     try {       const res = await fetch(url);       return await res.json();     } catch (e) {       console.log(e);       return {};     }   } }   export class InterfaceAxios extends InterfaceService {   constructor(props: ApiOptons) {     super(props);   }       private request = (requestCfg: AxiosRequestConfig): Promise<ResponseData> => {     return axios(requestCfg)       .then(this.checkStatus)       .catch((err: any) => {         // 后台接口异常,如接口不通、http状态码非200、data非json格式,判定为fatal错误         console.log(requestCfg, err);         return {           code: 408,           message: '网络异常',         };       });   };       private checkStatus(response: AxiosResponse<ResponseData>) {     if (response.status >= 200 && response.status < 300) {       return response.data;     }     return {       code: 408,       message: '网络数据异常',     };   }       public async post(url: string, data?: any) {     const toastId = this.preCheck();     const ret = await this.request({       url,       headers: this.headers,       method: 'POST',       data: Object.assign({ sysToken: this.sysToken }, data),     });     ret.toastId = toastId;      return ret;   }       public async get(url: string, params?: any) {     const toastId = this.preCheck();     const ret = await this.request({       url,       headers: this.headers,       method: 'GET',       params: Object.assign({ sysToken: this.sysToken }, params),     });     ret.toastId = toastId;     return ret;   } }  export class ServiceManager {      public hasNoError(res: ResponseData) {     if (res.toastId > 0) {       Toast.remove(res.toastId);     }     if (res?.code !== 0 && res.code !== codeUnknownTask) {       Toast.info(res?.message ?? '服务器出错');       return false;     }     return true;   }       public static parse<T>(     modal: { new (x: any): T },     response: any,     options: ApiOptons,   ): ResultDataType<T> {     if (!response || !response.data) {       response.data = new modal({});     } else {       if (response.data instanceof Array) {         response.data = response.data.map((item: T) => new modal(item));       } else if (response.data instanceof Object) {         response.data = new modal(response.data);       }       return options.onlyData ? response.data : response;     }   }       public static async post<T>(     modal: { new (x: any): T },     url: string,     body?: any,     options: ApiOptons = new ApiOptons(),   ): Promise<ResultDataType<T>> {     // 使用合并,减少外部传入配置     options = Object.assign(new ApiOptons(), options);      const request = new InterfaceAxios(options);     if (options.auth && !request.sysToken) {       return {         code: 403,         message: '未授权',       };     }      try {       const response = await request.post(url, body);       return ServiceManager.parse<T>(modal, response, options);     } catch (err) {       // 记录错误日志       console.log(url, body, options, err);       return {         code: codeUnknownTask,         message: '内部错误,请稍后再试',       };     }   }       public static async get<T>(     modal: { new (x: any): T },     url: string,     params?: any,     options: ApiOptons = new ApiOptons(),   ): Promise<ResultDataType<T>> {     // 使用合并,减少外部传入配置     options = Object.assign(new ApiOptons(), options);      const a = new InterfaceAxios(options);     const request = new InterfaceAxios(options);     if (options.auth && !request.sysToken) {       return {         code: 403,         message: '未授权',       };     }      try {       const response = await a.get(url, params);       return ServiceManager.parse<T>(modal, response, options);     } catch (err) {       // 记录错误日志       console.log(url, params, options, err);       return {         code: codeUnknownTask,         message: '内部错误,请稍后再试',       };     }   } }

Service文件里内容有点长,主要有下面几个类:

  • Toast:模拟请求接口时的loading,可通过接口调用时来配置;

  • InterfaceService:接口请求的基类,内部记录当前用户的Token、多环境服务器地址切换(代码中未实现)、单次请求的接口配置、自定义Header、请求前的逻辑检查、直接请求远端JSON配置文件;

  • InterfaceAxios:继承于InterfaceService,即axios版的接口请求,内部发起实际请求。你可以封装fetch版本的。

  • ServiceManager:提供给Model使用的请求类,传入响应Model和对应服务器地址后,等异步请求拿到数据后再将相应数据Data解析成对应的Model。

下面再贴一下完整的Model发起请求示例:

import { ResponseData, ApiOptons, SimpleModel } from './model';  // 接口配置不同的三种请求 SimpleModel.get({ id: '1' }).then((data: ResponseData) =>   setTimeout(     () =>       console.log(         '因需授权导致内部异常,返回 ResponseData:',         typeof data,         data,       ),     1000,   ), );  SimpleModel.get(   { id: '1' },   { auth: false, onlyData: false }, ).then((data: ResponseData<SimpleModel>) =>   setTimeout(     () =>       console.log(         '设置返回全部数据,返回 ResponseData<T> 或 ResponseData<T[]>',         typeof data,         data,       ),     2000,   ), );  SimpleModel.get(   { id: '1' },   { auth: false, onlyData: true }, ).then((data: SimpleModel) =>   setTimeout(     () =>       console.log(         '仅返回关键数据data,返回 T 或 T[]:',         typeof data,         data,         data.sexText(),       ),     3000,   ), );

控制台打印结果。注意,返回的 data 可能是JSON Object,也可能是 Immutable-js Record Object。

加载中... 2 加载中... 2 因需授权导致内部异常,返回 ResponseData:object { code: 403, message: '未授权' } 设置返回全部数据,返回 ResponseData<T> 或 ResponseData<T[]> object {   code: 0,   message: '1',   data: SimpleModel {     __ownerID: undefined,     _values: List {       size: 2,       _origin: 0,       _capacity: 2,       _level: 5,       _root: null,       _tail: [Vnode],       __ownerID: undefined,       __hash: undefined,       __altered: false     }   },   toastId: 1 } 仅返回关键数据data,返回 T 或 T[]:object SimpleModel {   __ownerID: undefined,   _values: List {     size: 2,     _origin: 0,     _capacity: 2,     _level: 5,     _root: null,     _tail: VNode { array: [Array], ownerID: OwnerID {} },     __ownerID: undefined,     __hash: undefined,     __altered: false   } } 男
最后再补充一个常见的复合类型Model示例:
  const ComplexChildOneDefault = {   name: 'lyc',   sex: 0,   age: 18, };  const ComplexChildTwoDefault = {   count: 10,   lastId: '20200607', };  const ComplexChildThirdDefault = {   count: 10,   lastId: '20200607', };  // const ComplexItemDefault = { //   userNo: 'us1212', //   userProfile: ComplexChildOneDefault, //   extraFirst: ComplexChildTwoDefault, //   extraTwo: ComplexChildThirdDefault, // };  // 复合类型建议使用class,而不是上面的object。因为object里不能添加可选属性? class ComplexItemDefault {   userNo = 'us1212';   userProfile = ComplexChildOneDefault;   extraFirst? = ComplexChildTwoDefault;   extraSecond? = ComplexChildThirdDefault; }  // const ComplexListDefault = { //   list: [], //   pageNo: 1, //   pageSize: 10, //   pageTotal: 0, // };  // 有数组的复合类型,如果要指定数组元素的Model,就必须用class class ComplexListDefault {   list: ComplexItemDefault[] = [];   pageNo = 1;   pageSize = 10;   pageTotal = 0; }  interface ComplexModelParams {   id: string; }  // 因为使用的class,所以需要 new 一个去初始化Record export class ComplexModel extends Record(new ComplexListDefault()) {   static async get(params: ComplexModelParams, options?: ApiOptons) {     return await ServiceManager.get<ComplexModel>(       ComplexModel,       'http://localhost:3000/test2',       params,       options,     );   } }

下面是调用代码:

ComplexModel.get({ id: '2' }).then((data: ResponseData) =>   setTimeout(     () =>       console.log(         '因需授权导致内部异常,返回 ResponseData:',         typeof data,         data,       ),     1000,   ), );  ComplexModel.get(   { id: '2' },   { auth: false, onlyData: false }, ).then((data: ResponseData<ComplexModel>) =>   setTimeout(     () =>       console.log(         '设置返回全部数据,返回 ResponseData<T> 或 ResponseData<T[]>',         typeof data,         data.data.toJSON(),       ),     2000,   ), );  ComplexModel.get(   { id: '2' },   { auth: false, onlyData: true }, ).then((data: ComplexModel) =>   setTimeout(     () =>       console.log(         '仅返回关键数据data,返回 T 或 T[]:',         typeof data,         data.toJSON(),       ),     3000,   ), );

接着是打印结果。这次Immutable-js Record Object就调用了data.toJSON()转换成原始的JSON Object。

加载中... 2 加载中... 2 因需授权导致内部异常,返回 ResponseData:object { code: 403, message: '未授权' } 设置返回全部数据,返回 ResponseData<T> 或 ResponseData<T[]> object {   list: [ { userNo: '1', userProfile: [Object] } ],   pageNo: 1,   pageSize: 10,   pageTotal: 0 } 仅返回关键数据data,返回 T 或 T[]:object {   list: [ { userNo: '1', userProfile: [Object] } ],   pageNo: 1,   pageSize: 10,   pageTotal: 0 }

感谢各位的阅读,以上就是“TypeScript在Model中的高级应用”的内容了,经过本文的学习后,相信大家对TypeScript在Model中的高级应用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: TypeScript在Model中的高级应用

本文链接: https://lsjlt.com/news/81533.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • TypeScript在Model中的高级应用
    这篇文章主要讲解了“TypeScript在Model中的高级应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“TypeScript在Model中的高级应用”...
    99+
    2024-04-02
  • java中RabbitMQ高级应用
    目录1、消息可靠性投递 1.1、确认模式 1.2、退回模式 1.3、确认机制2、消费端限流3、消息过期时间4、死信队列 4.1、死信概念&nb...
    99+
    2024-04-02
  • javascript的高级应用
    http://www.zzbang.cn/html/dev/js/2007/11/09/51/[@more@]1、关于javascript的apply和call函数 prototype.js中用了大量的apply和call函数,不注意会造成...
    99+
    2023-06-03
  • TypeScript 在 Vue.js 组件中的应用:实现高可维护性和复用性
    可维护性 TypeScript 的类型系统强制执行类型检查,这有助于及早发现错误并防止运行时错误。通过在编译时检查类型错误,TypeScript 可以帮助识别潜在的问题,从而提高代码的整体质量和可维护性。 此外,TypeScript 的自...
    99+
    2024-03-14
    TypeScript与Vue组件
  • 如何在Vue项目中应用TypeScript类
    目录一、前言二、使用1.@Component2.compued、data、methods3.@props4.@watch5.@emit三 、总结 一、前言 TypeScript是基于...
    99+
    2024-04-02
  • TypeScript在React中的应用技术实例解析
    目录引言为什么使用 TypeScript 开发 React 应用TypeScript 和 React 的结合方式...
    99+
    2023-05-16
    TypeScript应用React TypeScript React
  • TypeScript 在 VUE 中的应用:突破性能限制
    TypeScript 是 JavaScript 的超集,通过提供类型检查和编译时错误检查,显著增强了前端开发。在 Vue 中集成 TypeScript 可以极大地提高代码质量、可维护性和整体性能,从而带来许多优势。 性能提升 TypeS...
    99+
    2024-03-09
    Vue.js、TypeScript、性能优化、代码质量
  • PHP 函数在医疗保健行业中的高级应用
    PHP 函数在医疗保健行业中的高级应用 PHP 作为一种广泛使用的服务器端编程语言,在医疗保健行业中有着广泛的应用。通过利用 PHP 的强大函数,开发人员可以创建健壮且高效的应用程序,...
    99+
    2024-04-24
    医疗保健 php 敏感数据
  • TypeScript高级类型有哪些及怎么用
    本篇内容主要讲解“TypeScript高级类型有哪些及怎么用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“TypeScript高级类型有哪些及怎么用”吧!前言对于有 javascript 基础的...
    99+
    2023-06-05
  • java中RabbitMQ高级应用方法
    这篇文章主要介绍了java中RabbitMQ高级应用方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java中RabbitMQ高级应用方法文章都会有所收获,下面我们一起来看看吧。1、消息可靠性投递&e...
    99+
    2023-06-30
  • Golang技术在企业级开发中的应用对高并发应用的影响
    go技术凭借其并发性、高性能和易用性,在企业级高并发应用开发中发挥重要作用:并发性:go语言支持多线程并发,提高响应时间和吞吐量。高性能:编译执行和自动内存管理提升应用程序性能和可靠性。...
    99+
    2024-05-10
    golang 高并发 go语言 标准库
  • PHP 函数在移动应用程序开发中的高级用法
    php 函数在移动应用程序开发中可增强性能和功能。高级用法包括:数据序列化:转换复杂数据结构为存储或传输格式。远程过程调用:执行远程服务器上的函数调用。文件操作:读取和写入设备文件系统。...
    99+
    2024-04-23
    php 移动应用程序
  • C#枚举的高级应用
    文章开头先给大家出一道面试题: 在设计某小型项目的数据库(假设用的是 MySQL)时,如果给用户表(User)添加一个字段(Roles)用来存储用户的角色,你会给这个字段设置什么类型...
    99+
    2024-04-02
  • 文件高级应用
    目录 可读、可写(了解) 文件内指针移动(了解) seek(offset,whence) tell() read(n)...
    99+
    2023-01-31
    高级 文件
  • mogilefs高级应用(3)
    mogilefs高级应用架构图:实验说明:    1个mysql+3个即是mogstored又是tracker节点+1个nginx实现反代为了使用更少的主机,我们采用2台主机nginx + mogstored + tracker mysql...
    99+
    2023-01-31
    高级 mogilefs
  • Python编程的高级算法在Django API中的应用有哪些?
    Django是一个流行的Python Web框架,它提供了快速开发高质量Web应用程序所需的所有工具和功能。Django API是Django框架中的一部分,它允许开发人员构建RESTful API,并使用Python编程的高级算法来实现...
    99+
    2023-06-29
    编程算法 django api
  • Python中numpy容器的高级应用:如何在Laravel框架中实现?
    Python中的numpy容器是一种非常强大的数据结构,它可以在Laravel框架中实现很多高级的应用。下面让我们来看一些numpy容器的高级应用以及如何在Laravel框架中实现。 一、numpy容器的高级应用 多维数组 numpy中...
    99+
    2023-06-23
    numpy 容器 laravel
  • linux中awk高级应用的示例分析
    这篇文章主要为大家展示了“linux中awk高级应用的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“linux中awk高级应用的示例分析”这篇文章吧。处理前的文档: Mike ...
    99+
    2023-06-09
  • TypeScript 在 VUE 中的应用场景:解锁无限可能
    TypeScript 是一种强大的 JavaScript 扩展语言,近年来在 Web 开发中备受关注。它为 Vue.js 应用程序带来了诸多优势,包括更高的代码质量、更强的可维护性以及更快的开发速度。以下是一些 TypeScript 在...
    99+
    2024-03-09
    TypeScript, Vue, Web 开发, 代码质量, 可维护性
  • 你需要知道的TypeScript高级类型总结
    目录1. 字面量类型(1)字符串字面量类型(2)数字字面量类型(3)布尔字面量类型(4)模板字面量类型2. 联合类型(1)基本使用(2)限制(3)可辨识联合类型3. 交叉类型(1)基...
    99+
    2022-11-13
    TypeScript 高级类型
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作