精华内容
下载资源
问答
  • Apache与IIS的优劣对比点点评分析
  • 主要介绍了python:HDF和CSV存储优劣对比分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 虚拟DOM的实现原理和优劣对比

    千次阅读 2019-12-24 17:28:39
    虚拟DOM的实现原理和优劣对比

    虚拟DOM的实现原理和优劣对比


    Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化。

    虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。

    虚拟DOM概念随着react的诞生而诞生,由facebook提出,其卓越的性能很快得到广大开发者的认可;继react之后vue2.0也在其核心引入了虚拟DOM的概念;

    本章节,我们来逐步学习虚拟DOM的原理及其性能的优劣知识点梳理:

    什么是虚拟DOM ?

    虚拟dom可以看作是一个使用javascript模拟了DOM结构的树形结构,这个树结构包含整个DOM结构的信息,如下图所示:

    在这里插入图片描述

    为什么使用虚拟DOM ?

    之前使用原生js或者jquery写页面的时候会发现操作DOM是一件非常麻烦的一件事情,往往是DOM标签和js逻辑同时写在js文件里,数据交互时不时还要写很多的input隐藏域,如果没有好的代码规范的话会显得代码非常冗余混乱,耦合性高并且难以维护。

    另外一方面在浏览器里一遍又一遍的渲染DOM是非常非常消耗性能的,常常会出现页面卡死的情况;所以尽量减少对DOM的操作成为了优化前端性能的必要手段,vdom就是将DOM的对比放在了js层,通过对比不同之处来选择新渲染DOM节点,从而提高渲染效率。

    patch函数

    patch函数的执行分为两个阶段,两次传递的参数都是两个

    第一阶段为虚拟dom的第一次渲染,传递的两个参数分别是放真实DOM的container和生成的vnode,此时patch函数的作用是用来将初次生成的真实DOM结构挂载到指定的container上面。

    第二阶段传递的两个参数分别为vnode和newVnode,此时patch函数的作用是使用diff算法对比两个参数的差异,进而更新参数变化的DOM节点;

    可以发发现h函数和patch函数在cnabbdom中实现vdom到真实DOM的转化起到了至关重要的作用,那么还有一个很重要的环节,patch函数中是怎么样实现对比两个vnode从而实现对真实DOM的更新的呢,这里还要提一下snabbdom的另外一个核心算法,即diff算法。

    diff算法

    其实在我们日常开发中我们都在接触类似与diff算法的一些软件,比如svn可以看到当前代码和svn服务器上代码的不同之处,再如Beyond Compare这款软件也可以为我们指出两个对比文件的不同之处

    但是此处是如何实现对vnode的对比的呢?参考以下代码:

    let children = vnode.children || []         
    let newChildren = newVnode.children || []
    
    children.forEach(function(childrenVnode, index) {
        var newChildVnode = newChildren[index]  // 首先拿到对应新的节点
        if (childrenVnode.tag === newChildVnode.tag) {    // 判断节点是否相同
            updateChilren(childrenVnode, newChildVnode)   // 如果相同执行递归,深度对比节点
        } else {
            repleaseNode(childrenVnode, newChildVnode)    // 如果不同则将旧的节点替换成新的节点
        }
    })
    }
    
    
    function repleaseNode(vnode, newVnode) {    // 节点替换函数
        let elem = vnode.elem
        let newEle = createElement(newVnode)
    }
    

    总结

    • 虚拟DOM的实现原理:
      • 虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象
      • 状态变更时,记录新树和旧树的差异
      • 最后把差异更新到真正的dom中
    • 虚拟DOM的优劣如何?
      • 优点:
      • 保证性能下限: 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限
      • 无需手动操作DOM: 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率
      • 跨平台: 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等
      • 缺点:
      • 无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化,比如VScode采用直接手动操作DOM的方式进行极端的性能优化
    展开全文
  • weblogic部署方式nostage和stage优劣对比(英文版) weblogic部署方式nostage和stage优劣对比(英文版) weblogic部署方式nostage和stage优劣对比(英文版)
  • 关于openlayers与openscales的优劣对比,希望大神帮忙分析一下
  • 两者的优劣对比2.使用多线程的理由二、线程编程实战1.相关api的介绍2.初级实战代码13.初级实战代码2总结 前言 线程与进程在liunx系统编程中都是非常重要的一部分,并且两者有很多相似的地方,也有许多不同的地方,...
    
    
    


    前言

    线程与进程在liunx系统编程中都是非常重要的一部分,并且两者有很多相似的地方,也有许多不同的地方,今天我们来比较一下两者,并做一下线程编程实战

    一、线程与进程的对比

    1.两者的优劣对比

    UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情。有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务。  
      进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位。在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。

    线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程包含了表示进程内执行环境必须的信息,其中包括进程中表示线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno常量以及线程私有数据。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。在Unix和类Unix操作系统中线程也被称为轻量级进程(lightweight processes),但轻量级进程更多指的是内核线程(kernel thread),而把用户线程(user thread)称为线程。

    "进程——资源分配的最小单位,线程——程序执行的最小单位"

    进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

    2.使用多线程的理由

    从上面我们知道了进程与线程的区别,其实这些区别也就是我们使用线程的理由。总的来说就是:进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)。

    使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。

    使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。

    除了以上所说的优点外,不和进程比较,多线程程序作为一种多任务、并发的工作方式,当然有以下的优点:

    提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

    二、线程编程实战

    1.相关api的介绍

    1. 线程创建
      #include <pthread.h>
      int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
      // 返回:若成功返回0,否则返回错误编号
        当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
        新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

    2. 线程退出
        单个线程可以通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流:
        1)线程只是从启动例程中返回,返回值是线程的退出码。
        2)线程可以被同一进程中的其他线程取消。
        3)线程调用pthread_exit:
      #include <pthread.h>
      int pthread_exit(void *rval_ptr);
        rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。

    3. 线程等待
      #include <pthread.h>
      int pthread_join(pthread_t thread, void **rval_ptr);
      // 返回:若成功返回0,否则返回错误编号

    调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果例程只是从它的启动例程返回i,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。
      
      可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。
      
      如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。
      
    4线程ID获取及比较
    #include <pthread.h>
    pthread_t pthread_self(void);
    // 返回:调用线程的ID

    2.初级实战代码1

    #include <stdio.h>
    #include <pthread.h>
    
    void *func1(void *arg)
    {
    //      static int ret=10;//检验退出函数pthread_exit能否返回整数
            static char *p="wencai love pingping";//检验退出函数pthread_exit能否返回字符串
    
            printf("t1:%ld thread is creat\n",(unsigned long)pthread_self());//输出进程id号
    
            printf("t1 param is %d\n",*((int *)arg));
    
            pthread_exit((void *)p);//主动退出进程
    }
    
    void *func2(void *arg)
    {
    
            //static int ret=10;//检验退出函数pthread_exit能否返回整数
            static char *p="wencai love pingping";//检验退出函数pthread_exit能否返回字符串
    
            printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());//输出进程id号
    
            printf("t2 param is %d\n",*((int *)arg));
    
            pthread_exit((void *)p);//主动退出进程
    
    }
    
    int main()
    {
            int ret;
    
            int ret1;
    
            int param=100;
    
            char *pret=NULL;
    
            pthread_t t1;
    
            pthread_t t2;
    
            ret=pthread_create(&t1,NULL,func1,(void *)&param);//创建进程
    
            if(ret==0){
                    printf("main:creat t1 success\n");
                  }
    
            ret1=pthread_create(&t2,NULL,func2,(void *)&param);
    
            if(ret1==0){
                    printf("main:creat t2 success\n");
                    }
    
            printf("main:%ld\n",(unsigned long)pthread_self());
    
            pthread_join(t2,(void **)&pret);//等待进程开始,防止主线程结束,导致子线程提前结束。
    
            printf("main:t1 quit %s\n",pret);//检验返回的字符串
    
            printf("main:t2 quit %s\n",pret);
    
    
            return 0;
    }
    

    看看在liunx平台下的运行效果
    在这里插入图片描述
    可以看到两个线程都成功创建了,但不能体现线程的存储空间是共享的。因而下面的代码将能体现这个特点。

    3.初级实战代码2

    #include <stdio.h>
    #include <pthread.h>
    
    
    int data=0;//定义一个全局变量,用于检验线程存储空间的共享
    
    void *func1(void *arg)
    {
    
    //      static int ret=10;
            static char *p="wencai love pingping";
    
            printf("t1:%ld thread is creat\n",(unsigned long)pthread_self());
    
            printf("t1 param is %d\n",*((int *)arg));
    
            while(1){//利用死循环让线程打印多个全局变量的值,从运行结果来看,可以知道每次的值都是不连续的,因而证明了线程的存储空间是共享的。
                    printf("t1:data=%d\n",data++);
                    sleep(1);
                    }
    
    }
    
    void *func2(void *arg)
    {
            //static int ret=10;
            static char *p="wencai love pingping";
    
            printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());
    
            printf("t2 param is %d\n",*((int *)arg));
    
            while(1){//利用死循环让线程打印多个全局变量的值,从运行结果来看,可以知道每次的值都是不连续的,因而证明了线程的存储空间是共享的。
                    printf("t2:data=%d\n",data++);
                    sleep(1);
                    }
    
    }
    
    int main()
    {
            int ret;
    
            int ret1;
    
            int param=100;
    
            pthread_t t1;
    
            pthread_t t2;
    
            ret=pthread_create(&t1,NULL,func1,(void *)&param);
    
            if(ret==0){
                    printf("main:creat t1 success\n");
                    }
    
            ret1=pthread_create(&t2,NULL,func2,(void *)&param);
    
            if(ret1==0){
                    printf("main:creat t2 success\n");
                    }
    
            printf("main:%ld\n",(unsigned long)pthread_self());
    
            while(1){//利用死循环让线程打印多个全局变量的值,从运行结果来看,可以知道每次的值都是不连续的,因而证明了线程的存储空间是共享的。
                    printf("main:data=%d\n",data++);
                    sleep(1);
                    }
    
            pthread_join(t1,NULL);
    
            pthread_join(t2,NULL);
            
            return 0;
    }
    

    再来看看运行效果
    在这里插入图片描述
    可以看到两个线程对于全局变量data是共享的,这从而证明了线程存储空间是共享的

    总结

    对于上面线程相关的demo,我们可以看到,两个线程之间是相互竞争的,我们不知道哪个线程先执行,也无法操控线程运行的先后,因而在后续的博文中,将会引入条件变量和互斥量来实现对线程的控制。

    展开全文
  • PHP开发和JAVA开发网站的优劣对比有哪些?该篇文章由川软教育君整理并编辑:1、开发网站最好选用一个比较成熟、资料比较多的CMS,因为自己开发后台工作量也不小,JAVA的CMS比PHP要少很多,所以更多的人会将网站开发...

    PHP开发和JAVA开发网站的优劣对比有哪些?该篇文章由川软教育君整理并编辑:

    1、开发网站最好选用一个比较成熟、资料比较多的CMS,因为自己开发后台工作量也不小,JAVA的CMS比PHP要少很多,所以更多的人会将网站开发转向PHP语言。

    2、JAVA EE是一个很重的平台,部署起来要比PHP麻烦很多,不利于维护。

    3、JAVA语言本身也可以嵌入到JSP中,不过经过前辈的实践和总结,发现在JSP中写JAVA代码简直是惨不忍睹(当然这跟程序员有很大的关系),所以大师们提出了MVC,MVC虽然好,但是会给网站开发带来更多的工作量。

    4、PHP由于语法简单,这一点是我喜欢的地方(因为你用业余时间做开发,要的就是短平快,代码易懂,维护方便,用什么MVC都是自己作死啊),直接和HTML写在一起,即使PHP文件大较大,可读性也依然还行。

    5、PHP可以支持热部署,而JAVA需要重新编译。PHP改完一段代码,发布后就可以看到结果了,这省去了不少维护的工作量。

    6、JAVA可以做的事情PHP也可以做,所以对性能要求不高的网站或系统,可以用PHP来替代。

    7、PHP不适合开发大型的网站系统,PHP经过几代的发展,虽然性能上有了很大的提高,但和JAVA依然有差距,现在很多大型网站,后台的云计算,并发处理、数据库处理这些功能基本都用JAVA开发,而PHP则放在前台展现开发上,这样融合了JAVA和PHP的特点,使网站的申缩性理好。

    8、开发环境轻量化,对于PHP,我很少用IDE,我经常拿个记事本写代码,这一点我感觉和写JavaScrip一样,代码写的飞起!哈哈!而JAVA我则大部份要使用IDE,因为很多依赖关系和编译问题没有IDE你处理起来相当棘手。

    9、搜索引擎对PHP的支持现在也做的很好了,很多知名的CMS,搜索引擎都有一些相关的SEO插件。

    综上所述,川软教育君认为不管是PHP开发,还是JAVA开发网站,都要根据实际情况来定,如果是性能要求不高或者不算大太型的网站,建议PHP编程语言来开发,如果是大型网站,可以用JAVA编程开发。

    展开全文
  • Redis消息队列和KafKa优劣对比 redis 消息推送(基于分布式 pub/sub)多用于实时性较高的消息推送,并不保证可靠。 其他的mq和kafka保证可靠但有一些延迟(非实时系统没有保证延迟)。redis-pub/sub断电就清空,而...

    Redis消息队列和KafKa优劣对比

    redis 消息推送(基于分布式 pub/sub)多用于实时性较高的消息推送,并不保证可靠。
    其他的mq和kafka保证可靠但有一些延迟(非实时系统没有保证延迟)。redis-pub/sub断电就清空,而使用redis-list作为消息推送虽然有持久化,但并非完全可靠不会丢。

    另外一点,redis 发布订阅除了表示不同的 topic 外,并不支持分组,比如kafka中发布一个东西,多个订阅者可以分组,同一个组里只有一个订阅者会收到该消息,这样可以用作负载均衡。

    展开全文
  • python:HDF和CSV存储优劣对比分析小数据用csv,大数据用h5结论1:几百KB以上的数据都用h5比较好结论2:几KB的数据h5反而很慢程序import pandas as pdimport numpy as npfrom wja.wja_tool import test_time as tt...
  • Proxy与Object.defineProperty的优劣对比? Proxy的优势如下: Proxy可以直接监听对象而非属性 Proxy可以直接监听数组的变化 Proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等等是Object....
  • 工业相机千兆网线和USB优劣对比 工业相机的连接方式一般有千兆网线和USB两种,那么,它们有什么区别呢,哪一种连接方式更有优势呢? 工业相机千兆网线的优势:高数据传输率、现有以太网基础架构可用、较长的传输距离...
  • 二、优劣对比分析 (一)传统四大媒体的优劣性分析。 (1)优点:市场基础深厚,受众数量多。相对而言,传统四大媒体早在80年代就开始风靡社会,为广大受众所推崇和喜爱。80年代报纸的广告营业额曾一度占领第一位。...
  • Word 资料 在景观动画制作过程中软件3Dsmax与Lumion的优劣对比分析 姓 名_xxx_ 学 院_XXX_ 学 号_XXX_ 摘要 随着景观表现技术的不断进步和更新景观效果图已经不能完全满足设计师和甲方的要求因此景观动画变成了许多...
  • 以下是解析语言与编译性语言的一些优劣对比: 1:效率 编译比解析方式可能会取得更高的效率。一般情况下,在解析方式下允许程序时,解析程序可能需要反复扫描源程序。例如,每一次引用变量都要进行类型检查,甚至...
  • 基于列表和链表实现的序列优劣对比
  • XML各种解析方式优劣对比 1.) SAX(simpleAPI for XML)解析  SAX是事件驱动型XML解析的一个标准,SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束,元素(element)开始与结束等地方时...
  • promise generator async/await的优劣对比 Promise的写法只是回调函数的改进,使用then方法,只是让异步任务的两段执行更清楚而已。Promise的最大问题是代码冗余,请求任务多时,一堆的then,也使得原来的语义变得很...
  • 胖瘦AP组网优劣对比2019-11-22 14:29:351点赞21收藏1评论我们知道,在WLAN组网中通常会用到无线AP,AP在应用中通常有胖AP和瘦AP两种模式。 WLAN 组网方式通常分为2种:1、胖 AP + 有线交换机的分布式 WLAN 组网模式2...
  • mysql 001 | 3种mysql备份恢复方案优劣对比!点击上方“java进阶架构师”,选择右上角“置顶公众号”20大进阶架构专题每日送达前言这周又是上线周。办公桌的头发越来越多了,保温杯都是枸杞,电脑壁纸也换成了应急...
  • 下面美工铺子的小程序制作就给大家分别谈谈其优劣对比。 1、自研开发小程序 自研开发小程序,就是企业自己来开发,这就需要企业具备开发团队,其中包括策划、设计、前端、程序、运营等人员。企业只有具备这些技术...
  • 本文介绍Java中数组转为List三种情况的优劣对比,以及应用场景的对比,以及程序员常犯的类型转换错误原因解析。 一.最常见方式(未必最佳) 通过 Arrays.asList(strArray) 方式,将数组转换List后,不能对List增删,...
  • 本文介绍Java中数组转为List三种情况的优劣对比,以及应用场景的对比,以及程序员常犯的类型转换错误原因解析。 一.最常见方式(未必最佳) 通过 Arrays.asList(strArray) 方式,将数组转换List后,不能对List增删,...
  • 原标题:JAVA和PHP的优劣对比 这样从几个方面来看:一、运行机制:Java代码被编译成字节码后,会在虚拟机里由JIT进行二次编译成为本地码,据传言其执行速度可以和C++相媲美,经过我自己测试,用Java实现一个简单的...
  • 液晶&等离子电视优劣对比及选购指南
  • SEO优化和竞价优劣对比_做推广哪个好 对于很多中小企业来说,选择一种合适的推广方法是非常重要的,因为中小企业的推广预算有限,在这有限的预算里如果选错了推广方式,就会造成极大的损失,直接影响到企业的整体...
  • 传统媒体与新媒体对比优劣是怎样的呢?下面是小编整理的相关信息,让我们一起去看一下吧,希望可以给大家带来帮助。传统媒体对比新媒体的优劣相对于传统媒体而言,新媒体以一种新形势、新姿态、新技术实现市场切入...
  • 五大车载操作(VOS)系统优劣对比,车载系统架构分析-QNX系统性能分析 2017年08月13日 08:32:28 锋影Q 阅读数:7080 五大车载操作(VOS)系统优劣对比,车载系统架构分析-QNX.. 锋影 e-mail:174176320@qq.com ...
  • 微信小程序与传统APP十大优劣对比

    千次阅读 2017-01-05 07:59:00
    我们一起来看看传统APP与微信端小程序十大优劣对比 微信正让60%的APP变得没有存在价值,这个观点是从价值层面来谈的,以我们和传统企业合作实践的经验来看,从功能层面来看,未来,80%的传统APP将会被微信端小程序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,899
精华内容 759
关键字:

优劣对比