返回顶部
首页 > 资讯 > 精选 >vue编译器如何生成渲染函数
  • 334
分享到

vue编译器如何生成渲染函数

2023-06-26 05:06:29 334人浏览 八月长安
摘要

这篇文章主要讲解了“Vue编译器如何生成渲染函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue编译器如何生成渲染函数”吧!深入源码createCompiler() 方法 —— 入口文件

这篇文章主要讲解了“Vue编译器如何生成渲染函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue编译器如何生成渲染函数”吧!

vue编译器如何生成渲染函数

深入源码

createCompiler() 方法 —— 入口

文件位置:/src/compiler/index.js

其中最主要的就是 generate(ast, options) 方法,它负责从 AST 语法树生成渲染函数.

export const createCompiler = createCompilerCreator(function baseCompile(  template: string,  options: CompilerOptions): CompiledResult {    const ast = parse(template.trim(), options)    if (options.optimize !== false) {    optimize(ast, options)  }    const code = generate(ast, options)  return {    ast,    render: code.render,    staticRenderFns: code.staticRenderFns  }})

generate() 方法

文件位置:src\compiler\codegen\index.js

其中在给 code 赋值时,主要的内容是通过 genElement(ast, state) 方法进行生成的.

export function generate (  ast: ASTElement | void, // ast 对象  options: CompilerOptions // 编译选项): CodegenResult {    const state = new CodegenState(options)    const code = ast ? (ast.tag === 'script' ? 'null' : genElement(ast, state)) : '_c("div")'  return {    render: `with(this){return ${code}}`,    staticRenderFns: state.staticRenderFns  }}

genElement() 方法

文件位置:src\compiler\codegen\index.js

export function genElement (el: ASTElement, state: CodegenState): string {  if (el.parent) {    el.pre = el.pre || el.parent.pre  }  if (el.staticRoot && !el.staticProcessed) {        return genStatic(el, state)  } else if (el.once && !el.onceProcessed) {        return genOnce(el, state)  } else if (el.for && !el.forProcessed) {         return genFor(el, state)  } else if (el.if && !el.ifProcessed) {        return genIf(el, state)  } else if (el.tag === 'template' && !el.slotTarget && !state.pre) {        return genChildren(el, state) || 'void 0'  } else if (el.tag === 'slot') {        return genSlot(el, state)  } else {        let code    if (el.component) {            code = genComponent(el.component, el, state)    } else {      // 处理普通元素(自定义组件、原生标签)      let data      if (!el.plain || (el.pre && state.maybeComponent(el))) {                data = genData(el, state)      }            const children = el.inlineTemplate ? null : genChildren(el, state, true)             code = `_c('${el.tag}'${        data ? `,${data}` : '' // data      }${        children ? `,${children}` : '' // children      })`    }        for (let i = 0; i < state.transfORMs.length; i++) {      code = state.transforms[i](el, code)    }    // 返回 code    return code  }}

genChildren() 方法

文件位置:src\compiler\codegen\index.js

export function genChildren (  el: ASTElement,  state: CodegenState,  checkSkip?: boolean,  altGenElement?: Function,  altGennode?: Function): string | void { // 获取所有子节点  const children = el.children  if (children.length) {    // 第一个子节点    const el: any = children[0]    // optimize single v-for    if (children.length === 1 &&      el.for &&      el.tag !== 'template' &&      el.tag !== 'slot'    ) {            const normalizationType = checkSkip        ? state.maybeComponent(el) ? `,1` : `,0`        : ``      return `${(altGenElement || genElement)(el, state)}${normalizationType}`    }    // 获取节点规范化类型,返回一个 number: 0、1、2(非重点,可跳过)    const normalizationType = checkSkip      ? getNormalizationType(children, state.maybeComponent)      : 0    // 是一个函数,负责生成代码的一个函数    const gen = altGenNode || genNode         return `[${children.map(c => gen(c, state)).join(',')}]${      normalizationType ? `,${normalizationType}` : ''    }`  }}

genNode() 方法

文件位置:src\compiler\codegen\index.js

function genNode (node: ASTNode, state: CodegenState): string {  // 处理普通元素节点  if (node.type === 1) {    return genElement(node, state)  } else if (node.type === 3 && node.isComment) {    // 处理文本注释节点    return genComment(node)  } else {    // 处理文本节点    return genText(node)  }}

genComment() 方法

文件位置:src\compiler\codegen\index.js

// 得到返回值,格式为:`_e(xxxx)`export function genComment (comment: ASTText): string {  return `_e(${JSON.stringify(comment.text)})`}

genText() 方法

文件位置:src\compiler\codegen\index.js

// 得到返回值,格式为:`_v(xxxxx)`export function genText (text: ASTText | ASTExpression): string {  return `_v(${text.type === 2    ? text.expression // no need for () because already wrapped in _s()    : transformSpecialNewlines(JSON.stringify(text.text))  })`}

genData() 方法

文件位置:src\compiler\codegen\index.js

export function genData(el: ASTElement, state: CodegenState): string {  // 节点的属性组成的 JSON 字符串  let data = '{'    const dirs = genDirectives(el, state)  if (dirs) data += dirs + ','  // key,data = { key: xxx }  if (el.key) {    data += `key:${el.key},`  }  // ref,data = { ref: xxx }  if (el.ref) {    data += `ref:${el.ref},`  }  // 带有 ref 属性的节点在带有 v-for 指令的节点的内部,data = { refInFor: true }  if (el.refInFor) {    data += `refInFor:true,`  }  // pre,v-pre 指令,data = { pre: true }  if (el.pre) {    data += `pre:true,`  }  // 动态组件 <component is="xxx">,data = { tag: 'component' }  if (el.component) {    data += `tag:"${el.tag}",`  }    for (let i = 0; i < state.dataGenFns.length; i++) {    data += state.dataGenFns[i](el)  }    if (el.attrs) {    data += `attrs:${genProps(el.attrs)},`  }  // DOM props,结果 el.attrs 相同  if (el.props) {    data += `domProps:${genProps(el.props)},`  }    if (el.events) {    data += `${genHandlers(el.events, false)},`  }    if (el.nativeEvents) {    data += `${genHandlers(el.nativeEvents, true)},`  }    if (el.slotTarget && !el.slotScope) {    data += `slot:${el.slotTarget},`  }  // scoped slots,作用域插槽,data = { scopedSlots: '_u(xxx)' }  if (el.scopedSlots) {    data += `${genScopedSlots(el, el.scopedSlots, state)},`  }    if (el.model) {    data += `model:{value:${el.model.value      },callback:${el.model.callback      },expression:${el.model.expression      }},`  }    if (el.inlineTemplate) {    const inlineTemplate = genInlineTemplate(el, state)    if (inlineTemplate) {      data += `${inlineTemplate},`    }  }  // 删掉 JSON 字符串最后的 逗号,然后加上闭合括号 }  data = data.replace(/,$/, '') + '}'      if (el.dynamicAttrs) {    data = `_b(${data},"${el.tag}",${genProps(el.dynamicAttrs)})`  }  // v-bind data wrap  if (el.wrapData) {    data = el.wrapData(data)  }  // v-on data wrap  if (el.wrapListeners) {    data = el.wrapListeners(data)  }  return data}

genDirectives() 方法

文件位置:src\compiler\codegen\index.js

function genDirectives(el: ASTElement, state: CodegenState): string | void {  // 获取指令数组  const dirs = el.directives  // 不存在指令,直接结束   if (!dirs) return  // 指令的处理结果  let res = 'directives:['  // 用于标记指令是否需要在运行时完成的任务,比如 v-model 的 input 事件  let hasRuntime = false  let i, l, dir, needRuntime  // 遍历指令数组  for (i = 0, l = dirs.length; i < l; i++) {    dir = dirs[i]    needRuntime = true    // 获取节点当前指令的处理方法,比如 WEB 平台的 v-html、v-text、v-model    const gen: DirectiveFunction = state.directives[dir.name]    if (gen) {      // 执行指令的编译方法,如果指令还需要运行时完成一部分任务,则返回 true,比如 v-model      needRuntime = !!gen(el, dir, state.warn)    }    if (needRuntime) {      // 表示该指令在运行时还有任务      hasRuntime = true       // res = directives:[{ name, rawName, value, arg, modifiers }, ...]      res += `{name:"${dir.name}",rawName:"${dir.rawName}"${dir.value ? `,value:(${dir.value}),expression:${JSON.stringify(dir.value)}` : ''        }${dir.arg ? `,arg:${dir.isDynamicArg ? dir.arg : `"${dir.arg}"`}` : ''        }${dir.modifiers ? `,modifiers:${JSON.stringify(dir.modifiers)}` : ''        }},`    }  }  // 只有指令存在运行时任务时,才会返回 res  if (hasRuntime) {    return res.slice(0, -1) + ']'  }}

genDirectives() 方法

文件位置:src\compiler\codegen\index.js

function genProps(props: Array<ASTAttr>): string {  // 静态属性  let staticProps = ``  // 动态属性  let dynamicProps = ``  // 遍历属性数组  for (let i = 0; i < props.length; i++) {    // 属性    const prop = props[i]    // 属性值    const value = __WEEX__      ? generateValue(prop.value)      : transformSpecialNewlines(prop.value)    if (prop.dynamic) {       // 动态属性,`dAttrName,dAttrVal,...`      dynamicProps += `${prop.name},${value},`    } else {      // 静态属性,'attrName:attrVal,...'      staticProps += `"${prop.name}":${value},`    }  }  // 闭合静态属性字符串,并去掉静态属性最后的 ','  staticProps = `{${staticProps.slice(0, -1)}}`  if (dynamicProps) {    // 如果存在动态属性则返回:_d(静态属性字符串,动态属性字符串)    return `_d(${staticProps},[${dynamicProps.slice(0, -1)}])`  } else {    // 说明属性数组中不存在动态属性,直接返回静态属性字符串    return staticProps  }}

genHandlers() 方法

文件位置:src\compiler\codegen\events.js

export function genHandlers (  events: ASTElementHandlers,  isNative: boolean): string {  // 原生为 nativeOn,否则为 on  const prefix = isNative ? 'nativeOn:' : 'on:'  // 静态  let staticHandlers = ``  // 动态  let dynamicHandlers = ``     for (const name in events) {    const handlerCode = genHandler(events[name])    if (events[name] && events[name].dynamic) {      // 动态,dynamicHandles = `eventName,handleCode,...,`      dynamicHandlers += `${name},${handlerCode},`    } else {      // staticHandlers = `eventName:handleCode,...,`      staticHandlers += `"${name}":${handlerCode},`    }  }  // 闭合静态事件处理代码字符串,去除末尾的 ','  staticHandlers = `{${staticHandlers.slice(0, -1)}}`  if (dynamicHandlers) {    // 动态,on_d(statickHandles, [dynamicHandlers])    return prefix + `_d(${staticHandlers},[${dynamicHandlers.slice(0, -1)}])`  } else {    // 静态,`on${staticHandlers}`    return prefix + staticHandlers  }}

genStatic() 方法

文件位置:src\compiler\codegen\index.js

function genStatic(el: ASTElement, state: CodegenState): string {  // 标记当前静态节点已经被处理过了  el.staticProcessed = true    const originalPreState = state.pre  if (el.pre) {    state.pre = el.pre  }    state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`)  state.pre = originalPreState    return `_m(${state.staticRenderFns.length - 1    }${el.staticInFor ? ',true' : ''    })`}

genOnce() 方法

文件位置:src\compiler\codegen\index.js

function genOnce(el: ASTElement, state: CodegenState): string {  // 标记当前节点的 v-once 指令已经被处理过了  el.onceProcessed = true  if (el.if && !el.ifProcessed) {         return genIf(el, state)  } else if (el.staticInFor) {        let key = ''    let parent = el.parent    while (parent) {      if (parent.for) {        key = parent.key        break      }      parent = parent.parent    }    // key 不存在则给出提示,v-once 节点只能用于带有 key 的 v-for 节点内部    if (!key) {      process.env.NODE_ENV !== 'production' && state.warn(        `v-once can only be used inside v-for that is keyed. `,        el.rawAttrsMap['v-once']      )      return genElement(el, state)    }    // 生成 `_o(_c(tag, data, children), number, key)`    return `_o(${genElement(el, state)},${state.onceId++},${key})`  } else {          return genStatic(el, state)  }}

genFor() 方法

文件位置:src\compiler\codegen\index.js

export function genFor(  el: any,  state: CodegenState,  altGen?: Function,  altHelper?: string): string {  // v-for 的迭代器,比如 一个数组  const exp = el.for  // 迭代时的别名  const alias = el.alias  // iterator 为 v-for = "(item ,idx) in obj" 时会有,比如 iterator1 = idx  const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''  const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''  // 提示,v-for 指令在组件上时必须使用 key  if (process.env.NODE_ENV !== 'production' &&    state.maybeComponent(el) &&    el.tag !== 'slot' &&    el.tag !== 'template' &&    !el.key  ) {    state.warn(      `<${el.tag} v-for="${alias} in ${exp}">: component lists rendered with ` +      `v-for should have explicit keys. ` +      `See https://vuejs.org/guide/list.html#key for more info.`,      el.rawAttrsMap['v-for'],      true     )  }  // 标记当前节点上的 v-for 指令已经被处理过了  el.forProcessed = true // avoid recursion  // 返回 `_l(exp, function(alias, iterator1, iterator2){return _c(tag, data, children)})`  return `${altHelper || '_l'}((${exp}),` +    `function(${alias}${iterator1}${iterator2}){` +    `return ${(altGen || genElement)(el, state)}` +    '})'}

genIf() 方法

文件位置:src\compiler\codegen\index.js

// 处理带有 v-if 指令的节点,最终得到一个三元表达式,condition ? render1 : render2 export function genIf(  el: any,  state: CodegenState,  altGen?: Function,  altEmpty?: string): string {  // 标记当前节点的 v-if 指令已经被处理过了,避免无效的递归  el.ifProcessed = true // avoid recursion  // 得到三元表达式,condition ? render1 : render2  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)}function genIfConditions(  conditions: ASTIfConditions,  state: CodegenState,  altGen?: Function,  altEmpty?: string): string {  // 长度若为空,则直接返回一个空节点渲染函数  if (!conditions.length) {    return altEmpty || '_e()'  }  // 从 conditions 数组中拿出第一个条件对象 { exp, block }  const condition = conditions.shift()  // 返回结果是一个三元表达式字符串,condition ? 渲染函数1 : 渲染函数2  if (condition.exp) {        return `(${condition.exp})?${genTernaryExp(condition.block)      }:${genIfConditions(conditions, state, altGen, altEmpty)      }`  } else {    return `${genTernaryExp(condition.block)}`  }  // v-if with v-once should generate code like (a)?_m(0):_m(1)  function genTernaryExp(el) {    return altGen      ? altGen(el, state)      : el.once        ? genOnce(el, state)        : genElement(el, state)  }}

genSlot() 方法

文件位置:src\compiler\codegen\index.js

function genSlot(el: ASTElement, state: CodegenState): string {   // 插槽名称  const slotName = el.slotName || '"default"'  // 生成所有的子节点  const children = genChildren(el, state)  // 结果字符串,_t(slotName, children, attrs, bind)  let res = `_t(${slotName}${children ? `,function(){return ${children}}` : ''}`    const attrs = el.attrs || el.dynamicAttrs    ? genProps((el.attrs || []).concat(el.dynamicAttrs || []).map(attr => ({      // slot props are camelized      name: camelize(attr.name),      value: attr.value,      dynamic: attr.dynamic    })))    : null  const bind = el.attrsMap['v-bind']    if ((attrs || bind) && !children) {    res += `,null`  }  if (attrs) {    res += `,${attrs}`  }  if (bind) {    res += `${attrs ? '' : ',null'},${bind}`  }  return res + ')'}

genComponent() 方法

文件位置:src\compiler\codegen\index.js

function genComponent(  componentName: string,  el: ASTElement,  state: CodegenState): string {   // 所有的子节点  const children = el.inlineTemplate ? null : genChildren(el, state, true)  // 返回 `_c(compName, data, children)`,compName 是 is 属性的值  return `_c(${componentName},${genData(el, state)}${children ? `,${children}` : ''    })`}

总结

渲染函数的生成过程是什么?

编译器生成的渲染有两类:

  • render 函数,负责生成动态节点的 vnode

  • staticRenderFns 数组中的 静态渲染函数,负责生成静态节点的 vnode

渲染函数的生成过程,其实就是在遍历 AST 节点,通过递归的方式处理每个节点,最后生成格式如:_c(tag, attr, children, normalizationType)

  • tag 是标签名

  • attr 是属性对象

  • children 是子节点组成的数组,其中每个元素的格式都是 _c(tag, attr, children, normalizationTYpe) 的形式,

  • normalization 表示节点的规范化类型,是一个数字 0、1、2

静态节点是怎么处理的?

静态节点的处理分为两步:

  • 将生成静态节点 vnode 函数放到 staticRenderFns 数组中

  • 返回一个 _m(idx) 的可执行函数,即执行 staticRenderFns 数组中下标为 idx 的函数,生成静态节点的 vnode

v-once、v-if、v-for、组件 等都是怎么处理的?

  • 单纯的 v-once 节点处理方式 和 静态节点 一致

  • v-if 节点的处理结果是一个 三元表达式

  • v-for 节点的处理结果是可执行的 _l 函数,该函数负责生成 v-for 节点的 vnode

  • 组件的处理结果和普通元素一样,得到的是形如 _c(compName) 的可执行代码,生成组件的 vnode

感谢各位的阅读,以上就是“vue编译器如何生成渲染函数”的内容了,经过本文的学习后,相信大家对vue编译器如何生成渲染函数这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: vue编译器如何生成渲染函数

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

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

猜你喜欢
  • vue编译器如何生成渲染函数
    这篇文章主要讲解了“vue编译器如何生成渲染函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue编译器如何生成渲染函数”吧!深入源码createCompiler() 方法 —— 入口文件...
    99+
    2023-06-26
  • Vue在页面数据渲染完成之后如何调用
    这篇文章主要为大家展示了“Vue在页面数据渲染完成之后如何调用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Vue在页面数据渲染完成之后如何调用”这篇文章吧。在...
    99+
    2024-04-02
  • Vue如何监听数据渲染DOM完以后执行某个函数
    小编给大家分享一下Vue如何监听数据渲染DOM完以后执行某个函数,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!实例如下:&nbs...
    99+
    2024-04-02
  • vue2.0$nextTick如何监听数据渲染完成之后的回调函数
    这篇文章主要介绍vue2.0$nextTick如何监听数据渲染完成之后的回调函数,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!vue里面本身带有两个回调函数:一个是`Vue.next...
    99+
    2024-04-02
  • Vue编译器实现代码生成方法介绍
    这里将讨论如何根据JavaScript AST生成渲染函数的代码,即代码生成。代码生成本质上是字符串拼接的艺术。需要访问JavaScript AST中的节点,为每一种类型的节点生成相...
    99+
    2023-01-05
    Vue代码生成 Vue代码生成方案
  • 如何用 Timber 调试 PHP 函数的模版渲染?
    通过以下步骤调试 timber php 模版渲染:安装 timber 调试插件。在你的 config.php 文件中启用调试模式。在你的 twig 模版中使用 {{ dump() }} ...
    99+
    2024-04-23
    php timber composer
  • Vue项目中如何实现服务器端渲染
    本篇内容介绍了“Vue项目中如何实现服务器端渲染”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!vue-ssr在项目中的实践写在文前由于前端脚...
    99+
    2023-06-04
  • 如何解决vue数组和对象渲染的问题
    这篇文章给大家分享的是有关如何解决vue数组和对象渲染的问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。数组更新检测在 vue 中使用数组的push()、pop()、shift...
    99+
    2024-04-02
  • 如何解决vue数据渲染出现闪烁的问题
    这篇文章主要介绍了如何解决vue数据渲染出现闪烁的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在使用vue进行数据渲染的时候发现当我不...
    99+
    2024-04-02
  • 在vue.js渲染完界面之后如何再调用函数
    目录vue.js渲染完界面后调用函数1.下面开始介绍下2.运行之后3.此时查询官方api文档发现4.继续查询api文档发现5.最终把watch和nextTick组合一起6.运行后发现...
    99+
    2024-04-02
  • 编译器如何优化 C++ 内联函数?
    编译器优化内联函数的方法主要有:基于启发式:使用规则评估函数内联可能性。基于阈值的:超过设定阈值(如函数大小或调用次数)则不内联。基于配置文件的:使用运行时数据动态确定内联函数。 编译...
    99+
    2024-04-17
    c++ 内联函数
  • vue中watch如何自动检测数据变化实时渲染
    小编给大家分享一下vue中watch如何自动检测数据变化实时渲染,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!具体如下:首先确认...
    99+
    2024-04-02
  • 如何通过php函数解决页面渲染慢的问题?
    在开发网页应用的过程中,页面渲染慢是一个常见的问题。用户访问一个网页时,如果页面渲染时间过长,可能会导致用户的不耐烦,甚至放弃访问。因此,加快页面渲染速度对于提高用户体验和页面性能至关重要。PHP 是一种广泛使用的服务器端编程语言,它拥有丰...
    99+
    2023-10-21
    PHP函数 页面渲染
  • 如何对Python编译PyInstaller打包生成的exe文件进行反编译生成pyc、py源代码文件
    目录准备工作根据exe生成pyc文件根据pyc文件反编译为py文件参考总结准备工作 没有加壳的python编译并打包的exe文件python反打包代码(不知道这样叫是否合理):pyt...
    99+
    2023-01-18
    exe可以反编译成源码 exe程序反编译教程 如何反编译pyc文件
  • vue修改数据页面不重新渲染问题如何解决
    本文小编为大家详细介绍“vue修改数据页面不重新渲染问题如何解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue修改数据页面不重新渲染问题如何解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。vue渲染机制...
    99+
    2023-07-05
  • 如何解决Vue中引入swiper在数据渲染的时候,发生不滑动的问题
    这篇文章给大家分享的是有关如何解决Vue中引入swiper在数据渲染的时候,发生不滑动的问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。前几天在工作的过程中,在数据渲染的时候,...
    99+
    2024-04-02
  • Go 的编译器如何处理嵌套函数?
    问题内容 在 go 中编写嵌套函数时,编译器如何处理它?它是变成另一个函数并放在代码之外,还是在调用父函数时重新创建它? 例如: func funca() int { a :=...
    99+
    2024-02-05
    作用域
  • python如何生成高斯函数
    在python中使用random.gauss高斯随机数生成器生成高斯函数,具体方法如下:import randomdef trunc_gauss(mu, sigma, bottom, top): //使用随机库中的函数,其中包括高斯随机数生...
    99+
    2024-04-02
  • 如何在PHP中使用生成器函数
    在PHP中,生成器函数是一种强大的工具,可以帮助您高效地创建和处理大量数据。这种函数允许您生成一个序列,但是只在需要时才会计算下一个值,可以大大节省系统资源和执行时间。在这篇文章中,我们将介绍如何在PHP中使用生成器函数。什么是生成器函数?...
    99+
    2023-05-19
    PHP编程 生成器函数 迭代器对象
  • vue如何生成一个json数组
    这篇文章主要讲解了“vue如何生成一个json数组”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue如何生成一个json数组”吧!生成一个空的JSON数组首先,我们需要生成一个空的JSON...
    99+
    2023-07-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作