• 关于 js 无参数函数 的搜索结果

回答

不仅仅是ajax,ajax只是异步通信方式,你用同步的方式也可以实现跨域。 所以和是不是ajax没毛线关系。 什么是跨域: 浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),所以跨域就出现了. 上面提到的,同域的概念又是什么呢??? 简单的解释就是相同域名,端口相同,协议相同 jsonp: jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议。 一个是描述信息的格式,一个是信息传递双方约定的方法。 jsonp的产生: 1.AJAX直接请求普通文件存在跨域无权限访问的问题,不管是静态页面也好. 2.不过我们在调用js文件的时候又不受跨域影响,比如引入jquery框架的,或者是调用相片的时候 3.凡是拥有src这个属性的标签都可以跨域例如<script><img><iframe> 4.如果想通过纯web端跨域访问数据只有一种可能,那就是把远程服务器上的数据装进js格式的文件里. 5.而json又是一个轻量级的数据格式,还被js原生支持 6.为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback 参数给服务端, demo1:基于script标签实现跨域 举个例子:我在http://study.cn/json/jsonp/jsonp_2.html下请求一个远程的js文件 不通域的请求 被请求的数据,远程js的代码 这样就实现跨域成功了,因为服务端返回数据时会将这个callback参数(message)作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。 再写一个 Demo2: 基于script标签实现跨域 让远程js知道它应该调用的本地函数叫什么名字,只要服务端提供的js脚本是动态生成的就好了,这样前台只需要传一个callback参数过去告诉服务端,我需要XXX代码,于是服务端就会得到相应了. 例如 在http://study.cn/json/jsonp/jsonp_3.html页面请求 http://192.168.31.137/train/test/jsonpthree 上面说明了只要有src属性的都可以实现跨域请求,这个你应该清楚,当你引用某种js框架的时候不就是跨域了嘛,比如你引用谷歌juqery.js。 demo3:  基于jquery跨域 那么如何用jquery来实现我们的跨域呢???jquery已经把跨域封装到ajax上了,而且封装得非常的好,使用起来也特别方便 如果是一般的ajax请求: jsonp形式的ajax请求:并且通过get请求的方式传入参数,注意:跨域请求是只能是get请求不能使用post请求 jsonp 传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback) jsonpCallback 自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名 这里回调函数就是success 基本上就是这些了,还有iframe标签img标签,都可以,一个是描述信息的格式,一个是信息传递双方约定的方法。这个就算是跨域吧,跨域也就是只是一种格式。 答案来源网络,供参考,希望对您有帮助

问问小秘 2019-12-02 03:03:07 0 浏览量 回答数 0

问题

【精品问答】前端实战100例之JavaScript篇

珍宝珠 2020-02-14 15:10:56 1456 浏览量 回答数 1

回答

云函数(FaaS)是一段运行在云端的、轻量的、无关联的、并且可重用的代码。无需管理服务器,只需编写和上传代码,即可获得对应的数据结果。使用云函数可以使企业和开发者不需要担心服务器或底层运维设施,可以更专注代码和业务本身,也可以使代码进一步解耦,增加其重用性。 在客户端只需依赖mpserverless-sdk,在应用的上下文中进行简单的鉴权配置,即可调用云函数。 云函数的入参只有一个ctx对象,该对象可获取调用的云函数时传入的参数,也可获取小程序serverless服务空间的云数据库,云存储等服务。 例如,我们定义一个云函数,名为hello。代码如下所示: //云函数定义在index.js中,此文件为云函数的入口文件 module.exports = ctx => { const args = ctx.args; return { "text": args.hello, }; };云函数支持使用Node.js进行开发。您可将代码提交到云端运行,在客户端使用小程序Serverless提供的API进行调用。您还可以在云函数中直接通过API调用数据存储和文件存储的服务资源。 说明 目前云函数内不能调用其他云函数,只支持客户端的使用场景,例如支付宝小程序。 步骤一 定义云函数 关联上对应的后端云服务后,您可以在服务端目录中编写云函数的代码。 登录小程序云控制台,创建云函数。 详细操作,请参见新建云函数。 注意 云函数的名称必须和要上传的Node.js代码包名称一致。 新建云函数 在小程序的server/functions目录下创建云函数目录。 其中index.js是云函数getImageList的入口文件。 └── server/ └── functions └── getImageList └── index.js 编写云函数代码。 以下代码示例展示了如何从数据库images里面查出特定用户上传的图片记录。 module.exports = async (ctx) => { const images = await ctx.mpserverless.db.collection('images').find({ owner: ctx.args.username }); return { images }; }; 说明 云函数的返回值类型仅支持JSON格式。 打包云函数文件。 确保云函数文件名称和控制台上创建的云函数名称一致且为ZIP格式。 步骤二 部署云函数 编写云函数代码后,您需要将云函数代码上传至控制台发布代码。 在左侧导航栏,选择小程序Serverless > 云函数。 单击已创建的函数名称链接。 在发布管理页签,单击上传js包或更新js包,然后选择要上传的代码包。 说明 上传的代码包必须满足以下要求: 代码包的名称必须和在控制台上创建的函数名称一致。 代码包必须是.zip文件。 上传的代码包必须包含index.js文件。 上传成功后,单击代码部署。 步骤三 调用云函数 云函数代码发布后,在客户端您可以使用mpserverless.function.invoke方法调用上述定义的云函数。 以下代码示例展示了如何获取用户上传的图片记录,然后更新页面数据。 // 引入MPServerless模块 const MPServerless = require('@alicloud/mpserverless-sdk'); // 初始化MPServerless对象 const mpServerless = new MPServerless({ uploadFile: my.uploadFile, request: my.request, getAuthCode: my.getAuthCode, }, { appId: '1234456789', // 小程序应用标识 spaceId: 'db4dd657-7041-470a-90xxxxx', // 服务空间标识 clientSecret: '6c3c86xxxx6', // 服务空间 secret key endpoint: 'https://api.bspapp.com', // 服务空间地址,从小程序 serverless 控制台处获得 }); // 调用云函数getImageList mpServerless.function.invoke('getImageList', { username: 'Vincent', }).then((res) => { if (res.success && res.result) { this.setData({ imageList: res.result.images }); } }).catch(console.error); 云函数是一个后端服务,有时需要获得从客户端传来的参数。通过云函数内置的ctx.args方法,您可以获得从客户端传来的参数。 客户端代码 以下是客户端代码示例: await mpserverless.function.invoke('hello', { hello: 'world' }); 云函数代码 以下是云函数代码示例: module.exports = async ctx => { ctx.logger.info('hello %s', ctx.args.hello); }; 在云函数中,您可以直接调用同一环境(空间)的数据存储和文件存储服务。ctx.mpserverless在云函数封装了小程序的基础服务, API使用方式和客户端一致。 例如,要从数据存储获取数据,可以直接调用ctx.mpserverless.db方法: module.exports = async ctx => { const args = ctx.args; return await ctx.mpserverless.db.collection('user').find({ uid: args.uid }); }; 云函数(FaaS)是一段运行在云端的、轻量的、无关联的、并且可重用的代码。无需管理服务器,只需编写和上传代码,即可获得对应的数据结果。使用云函数可以使企业和开发者不需要担心服务器或底层运维设施,可以更专注代码和业务本身,也可以使代码进一步解耦,增加其重用性。 在客户端只需依赖mpserverless-sdk,在应用的上下文中进行简单的鉴权配置,即可调用云函数。 云函数的入参只有一个ctx对象,该对象可获取调用的云函数时传入的参数,也可获取小程序serverless服务空间的云数据库,云存储等服务。 云函数提供了 ctx.httpclient HTTP 请求方法。无需额外依赖,您就可以请求任何 HTTP 和 HTTPS 协议的 Web 服务。 例如,请求一个网页: module.exports = async ctx => { const res = await ctx.httpclient.request('https://www.alipay.com/x/notFound.htm'); return { html: res.status === 200 ? res.data : '', }; }; 其中,ctx.httpclient返回的是一个urllib实例。 云函数(FaaS)是一段运行在云端的、轻量的、无关联的、并且可重用的代码。无需管理服务器,只需编写和上传代码,即可获得对应的数据结果。使用云函数可以使企业和开发者不需要担心服务器或底层运维设施,可以更专注代码和业务本身,也可以使代码进一步解耦,增加其重用性。 在客户端只需依赖mpserverless-sdk,在应用的上下文中进行简单的鉴权配置,即可调用云函数。 云函数的入参只有一个ctx对象,该对象可获取调用的云函数时传入的参数,也可获取小程序serverless服务空间的云数据库,云存储等服务。

南霸天霸南北 2020-02-17 16:48:28 0 浏览量 回答数 0

新用户福利专场,云服务器ECS低至102元/年

新用户专场,1核2G 102元/年起,2核4G 699.8元/年起

回答

云函数(FaaS)是一段运行在云端的、轻量的、无关联的、并且可重用的代码。无需管理服务器,只需编写和上传代码,即可获得对应的数据结果。使用云函数可以使企业和开发者不需要担心服务器或底层运维设施,可以更专注代码和业务本身,也可以使代码进一步解耦,增加其重用性。 在客户端只需依赖mpserverless-sdk,在应用的上下文中进行简单的鉴权配置,即可调用云函数。 云函数的入参只有一个ctx对象,该对象可获取调用的云函数时传入的参数,也可获取小程序serverless服务空间的云数据库,云存储等服务。 例如,我们定义一个云函数,名为hello。代码如下所示: //云函数定义在index.js中,此文件为云函数的入口文件 module.exports = ctx => { const args = ctx.args; return { "text": args.hello, }; };云函数支持使用Node.js进行开发。您可将代码提交到云端运行,在客户端使用小程序Serverless提供的API进行调用。您还可以在云函数中直接通过API调用数据存储和文件存储的服务资源。 说明 目前云函数内不能调用其他云函数,只支持客户端的使用场景,例如支付宝小程序。 步骤一 定义云函数 关联上对应的后端云服务后,您可以在服务端目录中编写云函数的代码。 登录小程序云控制台,创建云函数。 详细操作,请参见新建云函数。 注意 云函数的名称必须和要上传的Node.js代码包名称一致。 新建云函数 在小程序的server/functions目录下创建云函数目录。 其中index.js是云函数getImageList的入口文件。 └── server/ └── functions └── getImageList └── index.js 编写云函数代码。 以下代码示例展示了如何从数据库images里面查出特定用户上传的图片记录。 module.exports = async (ctx) => { const images = await ctx.mpserverless.db.collection('images').find({ owner: ctx.args.username }); return { images }; }; 说明 云函数的返回值类型仅支持JSON格式。 打包云函数文件。 确保云函数文件名称和控制台上创建的云函数名称一致且为ZIP格式。 步骤二 部署云函数 编写云函数代码后,您需要将云函数代码上传至控制台发布代码。 在左侧导航栏,选择小程序Serverless > 云函数。 单击已创建的函数名称链接。 在发布管理页签,单击上传js包或更新js包,然后选择要上传的代码包。 说明 上传的代码包必须满足以下要求: 代码包的名称必须和在控制台上创建的函数名称一致。 代码包必须是.zip文件。 上传的代码包必须包含index.js文件。 上传成功后,单击代码部署。 步骤三 调用云函数 云函数代码发布后,在客户端您可以使用mpserverless.function.invoke方法调用上述定义的云函数。 以下代码示例展示了如何获取用户上传的图片记录,然后更新页面数据。 // 引入MPServerless模块 const MPServerless = require('@alicloud/mpserverless-sdk'); // 初始化MPServerless对象 const mpServerless = new MPServerless({ uploadFile: my.uploadFile, request: my.request, getAuthCode: my.getAuthCode, }, { appId: '1234456789', // 小程序应用标识 spaceId: 'db4dd657-7041-470a-90xxxxx', // 服务空间标识 clientSecret: '6c3c86xxxx6', // 服务空间 secret key endpoint: 'https://api.bspapp.com', // 服务空间地址,从小程序 serverless 控制台处获得 }); // 调用云函数getImageList mpServerless.function.invoke('getImageList', { username: 'Vincent', }).then((res) => { if (res.success && res.result) { this.setData({ imageList: res.result.images }); } }).catch(console.error);

南霸天霸南北 2020-02-17 16:49:19 0 浏览量 回答数 0

问题

在 berserkJS 中无缝使用 Wind.js:报错

kun坤 2020-06-07 14:00:40 0 浏览量 回答数 1

问题

JavaScript参数传递中值和引用的一种理解

云效平台 2019-12-01 21:19:51 2506 浏览量 回答数 1

问题

【javascript学习全家桶】934道javascript热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:22 6202 浏览量 回答数 1

问题

什么是函数计算事件处理函数

boxti 2019-12-01 21:48:44 866 浏览量 回答数 0

问题

支付宝小程序云训练营优秀学员提问来啦

问问小秘 2020-06-15 15:57:38 159 浏览量 回答数 1

回答

vue 双向数据绑定实现原理(数据劫持) ,卡槽slot,生命周期,getter, setter,nexttrick vue router hash 模式,history模式,meta参数,keep-alive,路由传值params和query的区别,redirct(重定向) vuex state, action, mutation,数据流 inject、provide mixin混入 eventbus vue axios 、axios 拦截器 es6 箭头函数(this指向),解构赋值 ,异步(promise–then、catch、all、finally;async–awit),设计模式,模块化,let 和 var 区别(作用域,变量提升)、pubsub Object.assign({}, item, ob); 解决vue双向数据绑定对对象属性的新增和删除不能及时响应的问题 Set 实现数组去重 filter 实现数组 arry.filter(item => item); 筛选 组件:组件间传值 ref、ref、ref、parent、 $emit, css预处理器:stylus,less,sass 打包工具:grunt,webpack typeScript :js超集 react svg(path,stroke, clip-path,mask,refs,use,滤镜, transform),canvas,css3 rxjs rxjs 集成到 vue node(koa) + nuxt + vue 无障碍阅读 quartz/corn jsDoc WebAssembly

问问小秘 2019-12-27 11:12:26 0 浏览量 回答数 0

回答

云端接入域名和端口号是什么? 域名:js ${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com 。 其中,${YourProductKey}请替换为您的产品ProductKey;${YourRegionId}请参见地域和可用区,替换为您在物联网平台创建产品时选择的地域代码。 端口: 1883。 使用MQTT协议连接,不同的设备可以使用相同的clientID连接服务器吗? clientID需为全局唯一。如果不同的设备使用相同的clientID同时连接物联网平台,那么先连接的那个设备会被强制断开。 如何开启域名直连? MQTT连接有两种方式。 认证后再连接:首先使用HTTPS连接到```js js iot-auth.cn-shanghai.aliyuncs.com:443 获取认证cert后,再使用MQTT连接到 ```js js/public.iot-as-mqtt.cn-shanghai.aliyuncs.com/1883。 认证连接必须使用TLS加密进行认证。 域名直连:连接域名:js ${productKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883 。 域名直连减少了HTTPS获取证书cert的过程。 资源受限的设备推荐使用域名直连。一些特殊增值服务,例如设备级别的引流,则推荐先HTTPS发送授权后再连接MQTT。在make.setting中设置js FEATURE_MQTT_DIRECT=y , 然后执行js make reconfig 即 可设置为先认证后再MQTT连接。 MQTT协议版本是多少? 在MQTT connect packet中设置MQTT的版本。目前SDK(V2.02)使用MQTT 3.1.1 。 可以修改SDK代码中js src\mqtt\mqtt_client.h IOTX_MC_MQTT_VERSION 的 值,来修改支持的版本。3:3.1版;4:3.1.1版。 MQTT进行设备认证时,server返回“400”错误 认证返回400错误,表示鉴权认证失败。请检查设备证书信息ProductKey、DeviceName和DeviceSecret是否正确。 C语言SDK中MQTT是否支持iOS接入? C语言SDK可以移植到任何能够支持C语言的系统上。如果是iOS系统建议寻找开源的Object-C实现。 目前mqtt-example设备上线后会立刻下线,请问如何修改mqtt-example让设备一直处于上线状态? mqtt-example程序发送一次消息后会自动退出,可以尝试以下任意一种方式实现长期在线。 执行mqtt-example时,使用命令行js ./mqtt-example loop , 设备会保持长期在线。修改demo代码。example 的代码在最后会调用IOT_MQTT_Destroy,设备最后会变成离线状态,所以可以修改代码,去掉IOT_MQTT_Unregister 和IOT_MQTT_Destroy。 while(1) { IOT_MQTT_Yield(pclient, 200); HAL_SleepMs(100); } 心跳的时间间隔如何设置? 在IOT_MQTT_Construct里面可以设置keepalive_interval_ms的取值。物联网平台使用这个值来作为心跳间隔时间。keepalive_interval_ms的取值范围是60000~300000。 设备端的重连机制是什么? 设备端会在keepalive_interval_ms时间间隔发送ping request,然后等待ping response。 如果设备端在keepalive_interval_ms时间内无法收到ping response,或是在进行send以及recv时发生错误,平台就认为此时网络断开,而需要进行重连。 重连机制是平台内部触发,无需使用者接入。重连时,会重新进行认证。如果认证成功就会开始再次进行MQTT connect。重连会一直持续直到再次连接成功。 云端如何侦测到设备离线? 云端会根据MQTT CONNECT packet里面keepalive的设置,等待ping request。如果在指定时间内没有收到ping request,则认为设备离线。 云端可以接受的最大时延是5秒。 设备端SDK是否支持MQTT和CCP协议的断线重连? 支持。测试场景描述:开发板通过WiFi连接上路由器后,把网线拔掉,MQTT和CCP协议都会自动尝试和server重新建立连接。尝试时间间隔是1s、2s、4s、8s、…,最大间隔时间默认是60s,也就是说断网后超过60s时间仍未连接成功,之后会每隔60s尝试和server重连。您可以设置最大间隔时间。 发布(Publish QoS1)数据时,偶尔会出现MQTT_PUSH_TO_LIST_ERROR(-42),如何解决? 需要等待ACK的packet都会存放起来,等待ACK。存放量有上限,当需要等待的packet太多到达上限时,就会触发js MQTT_PUSH_TO_LIST_ERROR(-42) error 。 出现错误可能是因为当前网络状态不好,或者是发送的频率过高。如果排除上述两个问题,当前的发送的频率是预期的,那么可以适当的调整IOTX_MC_REPUB_NUM_MAX、 IOTX_MC_SUB_REQUEST_NUM_MAX和IOTX_MC_SUB_NUM_MAX的大小。 如果业务允许,也可以把publish的QoS调整成0。 IOT_MQTT_Yield的作用是什么? IOT_MQTT_Yield的作用是尝试接收数据。因此在需要接收数据时,例如subscribe 和 unsubscribe之后,publish QoS1 消息之后,或是希望收到publish 数据时,都需要主动调用该函数。 IOT_MQTT_Yield参数timeout的意义是什么? IOT_MQTT_Yield会尝试接收数据,直到timeout时间到后才会退出。 IOT_MQTT_Yield与HAL_SleepMs的区别 IOT_MQTT_Yield与HAL_SleepMs都是阻塞一段时间,但是IOT_MQTT_Yield实质是去读取数据,而HAL_SleepMs则是系统什么也不做,等待timeout。 如何循环接收消息? 需要循环调用IOT_MQTT_Yield ,函数内自动维持心跳和接收数据。 订阅了多个Topic,调用一次IOT_MQTT_Yield,能接收到多个Topic的消息吗? 首先需要确定Topic的权限,是不是同时满足发布和订阅。如果是,调用一次IOT_MQTT_Yield,可以接收到多个packet。 MQTT连接方式,只能通过不停地调用IOT_MQTT_Yield来轮询获取数据吗? 如果使用的TCPIP协议栈,可以实现TCP主动通知上层有数据到达,可以改动实现事件触发的方式来触发IOT_MQTT_Yield。但是改动比较大,所以还请自行评估是否需要修改。 修改流程是: 调整utils_net.c里面socket的API,变成可以由TCP数据到达时回调的API。 当TCP主动通知上层有数据到达时,通知到MQTT服务器。让MQTT服务器内部执行IOT_MQTT_Yield,这样就可以不需要外部调用IOT_MQTT_Yield来读取数据。 如果TCP无法做到主动上报数据,但OS支持多线程,也可以在MQTT-example里面再起一个thread,在这个thread里面以下代码用于接收数据。收到数据时,触发主线程进行数据处理,而主线程大部分时间可以用于处理其他逻辑。 while(1) { IOT_MQTT_Yiled(pclient, 200); HAL_SleepMs(200); } 如果使用的系统也不支持多线程,就只能把IOT_MQTT_Yield的timeout时间间隔减小,然后提高调用的频率,在每次调用的时间间隔内执行其他操作,从而做到尽量减少对其他操作的阻塞。 是否支持QoS 2? 不支持。 什么情况下会发生订阅超时(subscribe timeout)? 在2倍request_timeout_ms时间内,系统未接收到SUBACK packet时,会触发订阅超时,并通过event_handle函数发送超时通知。 请在subscribe之后,立刻执行IOT_MQTT_Yield尝试读取SUBACK,请勿使用HAL_SleepMs。 subcribe时,返回IOTX_MQTT_EVENT_SUBCRIBE_NACK 请检查Topic的操作权限是否为订阅。 如果发布报错“no authorization”,请确认是否为发布权限。 MQTT 发布的消息体大小限制 MQTT的协议包受限于IOT_MQTT_Construct里参数的write_buf和read_buf的大小。 MQTT协议包大小不能超过256 KB。超过大小限制的消息会被丢弃。 MQTT协议pub消息payload格式是怎么样的? 物联网平台没有制定pub消息payload的具体字段有那些。您根据应用场景制定自己的协议,然后以JSON格式放到pub消息载体里面传给服务端。 ota_mqtt升级的时候报错“mqtt read buffer is too short” MQTT设置的buffer过小,即mqtt_param的pread_buf和pwrite_buf申请过小造成的。可以根据实际需要修改OTA_MQTT_MSGLEN的大小。 是否可以使用MQTT直连的方式进行OTA升级? OTA升级时,必须使用HTTPS进行固件下载。MQTT只接收版本更新指令,与MQTT的连接方式无关。阿里云不支持HTTP下载固件,因此如果设备没有SSL通信的能力,则不能使用OTA服务。 打开MQTT over TLS,运行时提示MQTT创建失败,返回错误码0x2700 如果关闭MQTT over TLS则可以成功地订阅和发布信息;打开MQTT over TLS时,建连失败。首先确认mbedtls是否做了修改,这是用于传输层和应用层之间加密的功能,不能随意更改。mbedtls没有修改,则考虑系统时间是否正确,系统时间不对也会导致证书校验失败。 进行mqtt连接的时候,是否需要root.crt证书验证? 若使用TLS进行MQTT接入,需要下载根证书。 若使用物联网平台提供的demo进行开发,无需再下载根证书,demo中已自带证书。 物联网平台支持哪些QoS Level? 在MQTT协议和CCP协议下,阿里云物联网平台支持的QoS Level都包括0和1。

剑曼红尘 2020-03-05 12:51:20 0 浏览量 回答数 0

回答

小程序项目通过编译之后,自动在模拟器中运行,无需真机即可快速预览。基础互 动方式是通过鼠标点击、拖拽来模拟手指触摸、拖动操作。 在默认设置下,每次保存已变更代码时都会触发模拟器自动刷新,实现准实时预览 效果。关闭自动刷新的方法:取消勾选模拟器右下角 自动更新。 模拟器布局 模拟器顶部各项功能(从左至右):  设备尺寸:选择预设的 iOS 或安卓设备尺寸,或者新建自定义的设备尺寸,用于测试适配 性。  缩放比例:控制小程序的显示缩放比例。  刷新:重新编译代码并刷新模拟器。  小工具:打开/关闭模拟器的小工具菜单。  模拟器日志:在编辑器打开模拟器日志窗口。  独立窗口:改用独立窗口方式显示模拟器。 在独立窗口模式下,界面新增 窗口置顶 按钮;独立窗口 变为 合并窗口 按钮。 模拟器底部三项功能:  页面路径:显示当前页面路径。点击路径,可直接打开当前页面 js 文件。  页面参数:显示当前页面收到的参数。点击参数,可快速复制至剪贴板。  自动刷新:如需避免频繁刷新,可取消勾选此功能。 说明:点击 ^ 可以切换显示 页面路径 或 页面参数。 模拟器小工具 点击图中蓝色小工具图标,显示/隐藏更多模拟功能: 首页:模拟按下 Home 键,小程序退回后台。用于测试生命周期函数 onShow 与 onHide,参见 小程序运行机制。 定位:输入设置 经纬度 模拟信息,用于测试 my.getLocation 获取用户位置端 口(经纬度模拟信息需要输入浮点数,精确至 1 位小数以上)。 扫码:输入设置 扫码返回数据 模拟信息,用于测试 my.scan 扫一扫端口。 摇一摇:模拟摇一摇动作,用于测试 my.watchShake 摇一摇端口。 授权:设置 用户信息、地理位置、相册、相机、麦克风 模拟权限,可用于测试 my.getLocation、my.chooseImage 等端口的权限请求步骤(在已获得用户信 息授权时,还提供删除用户信息授权的选项)。 裁剪:模拟用户截屏情况,用于测试 my.onUserCaptureScreen 截屏事件监听 端口。 内存警告:模拟内存不足情况,用于测试 my.onMemoryWarning 内存警告监听 端口。 mtop 环境切换:可进行环境切换,切换为 日常、预发、线上。 内容来源:https://developer.aliyun.com/article/756818?spm=a2c6h.12873581.0.dArticle756818.26162b70Su1GZy&groupCode=tech_library

KaFei 2020-04-27 13:48:44 0 浏览量 回答数 0

问题

企业应用接入的开发

kangknag 2019-12-01 21:18:58 3641 浏览量 回答数 1

问题

H5技术百问——不懂H5你就OUT啦

yq传送门 2019-12-01 20:27:41 42586 浏览量 回答数 47

回答

Beego https://beego.me/ Beego 框架提供了很多标准附加功能,例如全功能路由器和可用于执行 CRUD 操作的对象到数据库映射工具。Bee 是 Beego 爱好者的最爱,它是一个快速而强大的命令行工具,用于构建、更新、打包和部署应用程序。Bee 可以从模板生成源代码,并保持数据库的最新状态。 Buffalo https://gobuffalo.io/en Buffalo 团队需要能够将 Web 应用程序的所有部分组装在一起的东西,包括应用程序本身的一些设计。他们把能够安装在一起的很多部件叫作“生态系统”。如果你想要路由——很少有人不需要——Buffalo 就包含了 Gorilla/Mux。如果你需要模板,Buffalo 倾向于使用 Plush,而不是使用内置的 Go 语言模板机制。数据库连接模块集合 Pop 可以帮你将数据库信息转换为 Go 对象。你还可以找到连接数据库、处理 cookie 以及完成其他任务的标准方法。 Cobra https://github.com/spf13/cobra 有时候,你只需要一个命令行界面。Cobra 提供了 CLI 的所有标准功能,因此你不必浪费时间实现代码来查找 -h 或 -help 标志。如果你的微服务需要对具有大量标志和其他功能的命令行调用做出响应,那么可以考虑集成 Cobra。 Docker 你当然可以在办公室服务器小黑屋里的裸机上运行微服务,但越来越多的人将他们的代码捆绑在 Docker 容器中,并将容器发到云端。小型的包更容易处理大量不同的代码块,当你对微服务架构的愿景要求你创建很多小的独立代码块时,这将是一项有价值的服务。 值得一提的是,Docker 是用 Go 语言开发的,尽管在部署 Docker 容器时你可能永远不会想到这一点。Docker 社区版是开源的,所以如果有必要,你可以参与其中,但很可能你只是将 Docker 作为部署微服务的工具。Go 语言爱好者之所以想要记住 Docker 是用 Go 语言开发的这一事实,是因为无处不在的 Docker 有力地证明了他们对这门语言的支持。 Echo https://echo.labstack.com/ Echo 是一个极简框架,但它提供了很多最重要的组件。路由器可以将 URL 拆解,然后将拆解的各个部份转换为参数,因此你无需自行解析它们。然后,你可以混合使用身份验证、表单解析、压缩和合理性限制。你可以专注于从函数中返回正确的信息。 Errors https://github.com/juju/errors 有时候,API 的用户会传递错误的参数。你可以自己处理这些参数,也可以把它们创给 Errors,这是一个可以自动执行大部分跟踪的库,方便进行调试。当发生错误时,Errors 会使用注释来详细说明出错的地方和位置。 Gin https://github.com/gin-gonic/gin Gin 是 Martini( https://github.com/go-martini/martini )的下一代框架。可以说,Gin 抛弃了那些额外的东西,专注于提供最有用的部分。花费大量时间构建 Node.js 微服务的开发人员会感到宾至如归。你可以实例化一个对象,然后附加函数来处理特定的调用,这样就可以创建一个微服务。Gin 负责处理路由,而你的函数处理业务逻辑。如果不去考虑标点符号,它的代码甚至看起来有点像 Node.js 代码。 Ginkgo https://onsi.github.io/ginkgo/ 测试可能是微服务开发当中最具挑战性的事情。Ginkgo 通过行为驱动测试扩展了标准 Go 发行版的内置测试机制。Ginkgo 提供了一种高级机制,用于指定函数或服务应该产生哪些结果。结果通常使用 Ginkgo 提供的 Gomega 匹配器( http://onsi.github.io/gomega/ )进行评估,但如果你愿意,也可以使用不同的匹配器库。 Ginkgo 是一个全面的框架,提供了各种选项,用于设置测试数据、运行测试以及在事后释放测试数据。你只需要描述结果,然后让 Ginkgo 处理其他的事情。 Goa https://github.com/goadesign/goa 如果你是一个曾经使用 Ruby 和 Praxis 框架的开发人员,或者是一个欣赏设计语言的强大力量人,那么你会在 Goa 中找到很多你喜欢的东西。你本身不需要编写 Go 代码。你使用 Goa DSL 为 API 编写设计规范,然后 Goa 将其转换为可执行的 Go 代码。DSL 针对微服务 API 进行了优化,并强制你的设计遵循标准的架构。 Gorilla http://www.gorillatoolkit.org/ Gorilla 项目提供了一系列你需要的模块。Gorilla 的 Mux( http://www.gorillatoolkit.org/pkg/mux )路由器被很多其他框架使用,因为它太好用了。很多用户之所以使用 Gorilla,是因为 websocket( http://www.gorillatoolkit.org/pkg/websocket )。 Gotify https://github.com/gotify/server 同步一组微服务所面临的一个挑战是建立有效的消息传递节点。Gotify 是一个简单的服务器,用于发送和接收消息,将你的微服务集合与持续存储的消息组合在一起。最有用的部分可能是它的 Web 接口,可帮助开发者应对最令人头疼的调试问题。 Hugo https://github.com/gohugoio/hugo Hugo 是一种静态站点生成器,可以用这个框架构建的微服务并不多,但如果网站只有有限的重复查询答案时,这是一个值得考虑的选项。Hugo 一次生成答案,然后可以重复使用。如果你已经已 HTML 格式提供答案,那么 Hugo 会非常有用。 Kite https://github.com/koding/kite 如果你希望建立一个更加可控的服务群体,而不是通常的服务之间的互动,那么可以考虑一下 Kite。Kite 的目标是让微服务之间的通信协调变得更简单一些。来自 Kite 以外的 API 调用通过 websocket 进入,然后 Kite 使用更快、更低级别的套接字连接(基于 dnode)传递新消息。中间有一个叫作 Kontrol 的服务注册表和身份验证服务。如果你需要经常交换消息和协调很多的操作,那么在不同服务器之间添加这一层会让一切变得更快。 Logrus https://github.com/sirupsen/logrus 要跟踪 API 的流入和流出数据和可能产生的错误,通常需要将日志写入文件中。这个过程可以很简单,比如在一个打开的文件中写入一行行的数据,但通常使用完整的日志框架会更好。Logrus 提供了格式化程序来标准化你的日志输出,并让后续的自动化日志文件分析变得更容易。不要尝试自己开发日志代码,使用像 Logrus 这样的库会事半功倍。 Nano https://github.com/pasztorpisti/nano 构建一个微服务并不需要太多东西,Nano 就是一个极简主义的例子。它的实际代码不会超过 200 行,如果算上注释也只有 400 多行。你只需要几行代码就可以构建一个微服务——只包含处理请求所需的业务逻辑。这个框架还有一些其他不错的特性,例如与语言无关的 API 结构,这样你的 Go 代码就可以与使用其他语言开发的服务发生交互。它还提供了一个测试过程来,可以嵌入你的本地测试例程。简简单单,但却恰到好处。 Negroni https://github.com/urfave/negroni 有些人看完 Martini 后,决定走一条更简单的道路。他们剥离了路由器和其他一些东西,创建了 Negroni,这是一个非常小型的工具,除了处理标准文件、自定义请求、从基本错误中恢复以及保留日志之外,它不会做更多的工作。如果你想要额外的东西,可以自己加入。Negroni 团队也提供了一系列与可以与 Negroni 一起使用的小型项目。 Renderer https://github.com/thedevsaddam/renderer 在准备输出响应时,你需要获取数据并将其插入到模板中。Renderer 提供了各种输出格式(JSON、JSONP、XML、YAML、HTML、文件)和一个漂亮、快速和标准的模板引擎。 Revel https://revel.github.io/ Revel 借鉴了 Webpack 的一个简洁的特性,这让 Revel 看起来就像一个 IDE 一样,或者至少是 IDE 的一部分,每当你对代码做出更改,它会持续地重新构建你的项目。当你保存修改后,Revel 会检测到更改,然后就编译代码,如果没有编译错误,就启动应用程序。因此,Revel 服务器会自动部署修改的码——在桌面上进行开发时这项功能非常好用,或许对于生产环境代码部署来说也是有点诱人的。 这个框架本身功能齐全,它提供了模板、缓存、验证和过滤器。如果你正在构建很多微服务,它还提供了一个模块系统,让你可以在项目之间共享一些 MVC 组件。 Testify https://github.com/stretchr/testify 使用断言的最简单方法之一是使用 Testify,它是一个 Go 语言项目,还提供了模拟工具,用于快速测试大型微服务的各个部分。只需要几行代码就编写一些基本测试用例。 Tollbooth https://github.com/didip/tollbooth 在你发布 API 之后,当然希望来自世界各个角落的人都可以调用它。但当你的服务器发生熔断,或者你看一看为了获得弹性而为云托管账户支付的费用时,你可能会改变主意。Tollbooth 是一个用于限制传入请求的轻量级系统。限制前门的流量就等于减少了对管道中微服务或数据库的需求,让一切保持运行顺畅。 不使用框架 你只需从头开始编写 Go 代码,不需要导入任何依赖项或者实例化任何控制对象。使用 Go 语言创建微服务其实很容易,因为它已经内置了很多基本代码。这就是为什么只用几百行代码就可以构建出像 Nano 这样的框架。 监听套接字、解压缩 HTTP 请求等工作都是通过标准库完成的。虽然框架提供了一些额外的功能,但很多时候如果你需要一个非常基本的微服务,就不需要用到框架。太多的“附加功能”可能反而会妨碍你,而且 Go 开发人员可能会说,太多的依赖反而让 Go 语言变得更复杂。

有只黑白猫 2020-01-08 11:53:57 0 浏览量 回答数 0

回答

木心的《从前慢》里说: 记得早先少年时 大家诚诚恳恳 说一句 是一句 …… 从前的日色变得慢 车,马,邮件都慢 一生只够爱一个人 从前的锁也好看 钥匙精美有样子 你锁了 人家就懂了 木心怀念着过去那个通过邮件传递信息的简单时代。 当下的网络时代虽然瞬息万变,但传递信息也是一样的“说一句,是一句”,“你 锁了,人家就懂了”。 小程序经常需要往服务器传递数据或者从服务器拉取信息。 当用户通过小程序加载服务器传来的信息时,整个网络过程如下: 1. 用户通过小程序向服务器发出 GET 请求, 2. 服务器发送一个响应,响应信息包含一个数据文件。 上面的流程也许过于简化,其实用户与服务器之间不可能面对面直接通话,因为它 们相隔不是很近,甚至服务器是在浏览器的千里之外,而客户端浏览器不可能直通 服务器。 每一次的网络请求,小程序传递给服务器的信息,中间经过多重的信息转达。同理 服务器回应小程序的响应也是同样的路径。 通俗点说,就是传纸条的原理。写字条的同学需要把字条递给旁边第一个同学,然 后第二个同学递给第三个同学,以此类推,一直传递到最后的信息接收者。 让我们看看,在传递字条的过程中,如果信息发出者想要给信息最末尾的接受者告 白,会发生什么呢? 在HTTP 状态下,传递者都可以打开字条,查看里面的内容。而且发送信息者无法知道传输路径,一旦发生信息窃取,甚至不知道是谁窃取的。 还是就是当信息落入心怀不轨的人手中,或者篡改信息内容,其后果不可设想。比如,把“你喜欢我吗?”篡改成“你不喜欢我吗?”。 为了避免这些情况发生,HTTP 安全版本应运而生,即HTTPS。通过HTTPS,传送的每次信息都被加上一个锁。 该锁配套的公钥和密钥仅小程序和服务器知道,其他传递者无法获取。因此,无论客户端发送的信息经过多个路由器,他人都无法读取信息内容。客户端发送初始信息到服务器时,在信息内容中包含服务器的名称(在名为“服务器名称指示”的字段中)。而服务器运行商可以在同一台计算机上运行多个站点, 因此运行商可以跟踪到客户端的访问轨迹。虽然初始的信息已设置了加密,但是初始请求是仍未加密的。这就是通过小程序my.request 安全传递告白信息的故事。本节将介绍如何使用my.request API 实现网络请求,并介绍一些使用注意事项。版本要求:基础库1.11.0 或更高版本;支付宝客户端10.1.32 或更高版本,若版本较低,建议做兼容处理。 my.request 目前只支持HTTPS 协议的请求。 使用说明:  请预先在 支付宝小程序管理中心 > 小程序详情 > 设置 > 开发设置 > 服务器域名白名单 中配置域名白名单。小程序在以下 API 调用时只能与白名单中的域名进行通讯:HTTP 请 求(my.request)、上传文件(my.uploadFile)、下载文件(my.downloadFile)和 WebSocket(my.connectSocket)。  添加服务器域名白名单后,需要重新打包上传生成体验版,服务器域名才会生效。  在 IDE 上进行调试时,请使用真机预览调试。  支付宝客户端已不再维护 my.httpRequest,建议使用 my.request。另外,钉钉客户端尚 不支持 my.request。若在钉钉客户端开发小程序,则需要使用 my.httpRequest。 扫码体验 重要:  小程序开发过程中,可在开发工具内 详情 > 域名信息 > 忽略 httpRequest 域名合法性 检查 中选择是否忽略域名合法性检查,如果选择忽略,则在模拟器、预览以及真机调试场 景不会校验域名合法性,但小程序上线前必须确保通讯域名在白名单内,否则在正式版本无 法调用。  my.request 的请求头默认值为 {'content-type': 'application/json'},而不是{'contenttype': 'application/x-www-form-urlencoded'}。此外,请求头对象里面的 key 和 value 必须是 String 类型。 示例代码 my.request({ url: 'https://httpbin.org/post', method: 'POST', data: { from: '支付宝', production: 'AlipayJSAPI', }, dataType: 'json', success: function(res) { my.alert({content: 'success'}); }, fail: function(res) { my.alert({content: 'fail'}); }, complete: function(res) { my.hideLoading(); my.alert({content: 'complete'}); } }); // dataType 为 base64 示例 my.request({ url: 'https://gw.alipayobjects.com/mdn/miniapp_de/afts/img/A*G1kWSJbe2zEAAAAA AAAAAABjARQnAQ', method: 'GET', dataType: 'base64', success: (resp) => { console.log('resp data length', resp.data.length); console.log('resp data', resp.data); // 返回格式类似于: data:image/png;base64,iVBORw0KG... }, fail: (err) => { console.log('error', err); }, }) 入参 Object 类型,属性如下: 属性 类型 必填 描述 url String 是 目标服务器 URL。 headers Object 否 设置请求的 HTTP 头对象,默认 {'content-type': 'application/json'},该对象里面 的 key 和 value 必须是 String 类型。 method String 否 默认 GET,目前支持 GET/POST/PUT/DELETE。 data Object 否 详见 data 参数说明。 timeout Number 否 超时时间,单位 ms,默认 30000。 dataType String 否 期望返回的数据格式,默认 JSON,支持 JSON、text、 base64、arraybuffer (10.1.70 版本开始支持) 。 success Function 否 调用成功的回调函数。 fail Function 否 调用失败的回调函数。 complete Function 否 调用结束的回调函数(调用成功、 失败都会执行)。 data 参数说明 传给服务器的数据最终会是 String 类型,如果 data 不是 String 类型,会被 转换成 String 。转换规则如下:  若方法为 GET,会将数据转换成 query string: encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=enc odeURIComponent(v)...  若方法为 POST 且 headers['content-type'] 为 application/json ,会对数据进行 JSON 序列化  若方法为 POST 且 headers['content-type'] 为 application/x-www-formurlencoded ,会将数据转换成 query string: encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=enc odeURIComponent(v)... success 回调函数 入参为 Object 类型,属性如下: 属性 类型 描述 data String 响应数据,格式取决于请求时的 dataType 参数, 如果 dataType 值为 base64 时,返回的是符合 data URI scheme 规范的内容字符串。 status Number 响应码。 headers Object 响应头。 返回值 RequestTask 网络请求任务对象。调用 my.request 后返回的请求对象。 RequestTask.abort() 中断请求任务。 示例代码 const task = my.request({url: 'https://httpbin.org/post'}) task.abort(); “抱歉,不是我的菜”:小程序扫码点餐化解尴 尬 月上柳梢头,人约黄昏后。 周五到了,小心翼翼约她出来吃晚饭,她欣然应约。 餐厅位于徐汇区闹中取静的华山路,法式梧桐的点缀让餐厅更显典雅,也更富有异 国情调。踏入餐厅,灯光是橘色的,餐具是蓝的,桌椅也是蓝的,让人恍惚之间有 到了爱琴海边的错觉,唯美的装修风格、充满欧洲风味的精致美食,处处洋溢着地 中海风情,真浪漫啊。 她翩翩而至,裙裾飞扬。 见到她我脸红了。我紧张地问她要吃些什么,又手忙脚乱地叫来服务员点完了菜, 脸上冒出了小汗珠。 窗外的小雨滴滴答答,窗内的我们显得格外安静。 我鼓起勇气,打破沉默,小声问道:“你……你对我印象如何?” “抱歉,不是我的菜……” 此刻,我如同五雷轰顶,只觉天旋地转,眼前华光溢彩的餐厅瞬间变得黯淡了。 “你是不是点错菜了?还是上错菜了呢?”她指着桌上的法式田螺和奶油蘑菇汤, 瞪大了眼睛问我。旁边站着满脸疑惑的上菜员。 如何化解点错菜的尴尬呢?这时就需要使用支付宝小程序扫码点餐的功能了。 为了让用户减少输入,我们可以把复杂的信息编码成一个二维码,利用 my.scan API 调起支付宝扫一扫,用户扫码之后,my.scan 的 success 回调会收到这个 二维码所对应的字符串信息。 例如餐厅点餐的小程序,我们给餐厅中每个餐桌编号 1-100 号,把这个数字编码 到二维码中,扫码获得编号之后,就可以知道是哪一桌点的菜,大大提高点餐体验 和效率。 //page.js Page({ // 点击“扫码订餐”的按钮,触发 tapScan 回调 tapScan: function() { // 调用 my.login 获取微信登录凭证 my.scanCode({ success: function(res) { var num = res.result // 获取到的 num 就是餐桌的编号 } }) } }) 还有很多场景可以结合支付宝 App 扫码能力做到很好的体验,例如通过扫商品 上的一维码做一个商品展示的小程序;通过扫共享单车上的二维码去开启单车。我 们可以多思考如何利用这个扫码能力去替代一些繁琐的输入操作,让我们的小程序 变得更加便捷。 示例代码 // API-DEMO page/API/scan-code/scan-code.json { "defaultTitle": "Scan" <!-- API-DEMO page/API/scan-code/scan-code.axml--> <view class="page"> <view class="page-section"> <form onSubmit="scanCode"> <view> <button type="primary" onTap="scan">扫码</button> </view> </form> </view> </view> // API-DEMO page/API/scan-code/scan-code.js Page({ scan() { my.scan({ type: 'qr', success: (res) => { my.alert({ title: res.code }); }, }); } }) 入参 Object 类型,属性如下: 内容来源:https://developer.aliyun.com/article/756818?spm=a2c6h.12873581.0.dArticle756818.26162b70Su1GZy&groupCode=tech_library

KaFei 2020-04-27 15:46:55 0 浏览量 回答数 0

回答

浅谈Flutter框架原理及其生态圈 Flutter的锋芒 跨平台高性能的渲染引擎逐渐成为移动端、大前端领域的一个热点,作为其中的明星框架Flutter,经过近几年来的迅速发展,由极大的可能成为下一代跨端终端解决方案。自从2017 年 5 月,谷歌公司发布的了 Alpha 版本的 Flutter; 2018 年底 Flutter Live 发布的 1.0 版本;2019年7月发布1.5版本,截止今日(2020年2月)已经发布了v1.14.6 Beta版本。 在Flutter诞生之前,已经有许多跨平台UI框架的方案如Cordova、ReactNative、weex、uni-app、Hippy等,常见的需要处理兼容的终端平台也包括android、ios、web、Iot等,但是在大前端的浪潮下,对于企业和开发者来说开发效率和使用体验都十分重要,传统的做法莫过于分不同的团队开发不同的终端项目,如果还要继续向其他平台,拓展的话,我们需要付出的成本和时间将成倍增长。正因为如此,在这样的背景下,Flutter等跨端框架的兴起,从本质上讲,帮助开发者增加业务代码的复用率,减少因为要适配多个平台带来的工作量,从而降低开发成本、提高开发效率。 纵观已有的跨端方案,可以分为三类:Web 容器、泛 Web 容器、自绘引擎框架。 基于web容器即基于浏览器的跨平台也做得越来越好,自然管线也越来越短,与native的一些技术手段来实现性能上的相互补充。比如Egret、Cocos、Laya这些游戏引擎,它们在跨平台方面的做法多以Typescript编写,在iOS和安卓平台的各种浏览器中轻松的运行HTML5游戏,并在不同平台浏览器里提供近乎一致的用户体验,比如Egret还会提供高效的 JS-C Binding 编译机制,以满足游戏编译为原生格式的需求,不过大多数HTML游戏引擎也属于web容器这个范畴内。web容器框架也有一个明显的致命(在对体验&性能有较高要求的情况下)的缺点,那就是WebView的渲染效率和JavaScript执行性能太差。再加上Android各个系统版本和设备厂商的定制,很难保证所在所有设备上都能提供一致的体验。 泛 Web 容器框架比如ReactNative和Weex,即上层通过面向前端友好的UI,下层通过native的渲染形式,虽然同样使用类HTML+JS的UI构建逻辑,但是最终会生成对应的自定义原生控件,以充分利用原生控件相对于WebView的较高的绘制效率,同时H5与native相互补充来达到更好的用户体验,这也是一种很好的解决方案。缺陷也很明显,随着系统版本变化和API的变化,开发者可能也需要处理不同平台的差异,甚至有些特性只能在部分平台上实现,这样框架的跨平台特性就会大打折扣。 自绘引擎框架这里专指Flutter框架,从底层就承担跨端的任务和渲染方式,从目前来看,从技术的实现和方案的成熟度、产品的性能方面比较,Flutter有很大可能成为下一代主流跨平台框架。 Flutter与其他跨端框架的不同点之一就是自带渲染引擎,Flutter渲染引擎依靠跨平台的Skia图形库来实现,Skia引擎会将使用Dart语言构建的抽象的视图结构数据加工成GPU数据,交由 OpenGL 最终提供给 GPU 渲染,至此完成渲染闭环,因此可以在最大程度上保证一款应用在不同平台、不同设备上的体验一致性。 而开发语言选用的是同时支持 JIT和 AOT的 Dart语言,Dart本身提供了三种运行方式,应对web环境,用Dart2js编译成JavaScript代码,运行在常规浏览器中;使用DartVM直接在命令行中运行Dart代码;AOT方式编译成机器码,例如Flutter App框架。而且Dart 避免了抢占式调度和共享内存,可以在没有锁的情况下进行对象分配和垃圾回收,在性能方面表现相当不错,不仅保证了开发效率,代码性能和用户体验也更卓越。因此,Flutter在各类跨平台移动开发方案中脱颖而出。同时在去年2019的Google IO大会上,备受关注的Fuchsia系统虽然并没有发布,但是宣布了 Flutter除了支持开发 Android 和 iOS 程序之外,现在还支持开发Web程序了,在 I/O 大会上,谷歌发布了 Web 版 Flutter 的首个技术预览版,宣布 Flutter 将为包括 Google Home Hub 在内的 Google Smart Display 平台提供技术支持,并迈出利用 Chrome 操作系统支持桌面级应用的第一步。 很多JS开发者会思考Google Flutter团队至于为啥选择Dart而不是JS,其实Google 公司给出的原因很简单也很直接:Dart 语言开发组就在隔壁,对于 Flutter 需要的一些语言新特性,能够快速在语法层面落地实现;而如果选择了 JavaScript,就必须经过各种委员会(TC39等)和浏览器提供商漫长的决议。 Flutter绘制原理 在计算机系统中,图像的显示需要 CPU、GPU 和显示器一起配合完成:CPU 负责图像数据计算,GPU 负责图像数据渲染,而显示器则负责最终图像显示。 CPU 把计算好的、需要显示的内容交给 GPU,由 GPU 完成渲染后放入帧缓冲区,随后视频控制器根据垂直同步信号(VSync)以每秒 60 次的速度,从帧缓冲区读取帧数据交由显示器完成图像显示。 操作系统在呈现图像时遵循了这种机制,而 Flutter 作为跨平台开发框架也采用了这种底层方案。下面有一张更为详尽的示意图来解释 Flutter 的绘制原理。可以看到,Flutter 关注如何尽可能快地在两个硬件时钟的 VSync 信号之间计算并合成视图数据,然后通过 Skia 交给 GPU 渲染:UI 线程使用 Dart 来构建视图结构数据,这些数据会在 GPU 线程进行图层合成,随后交给 Skia 引擎加工成 GPU 数据,而这些数据会通过 OpenGL 最终提供给 GPU 渲染。 Skia原理 Skia 是一款用由C++ 开发的2D 图像绘制引擎。在2005 年被 Google 公司收购后被广泛应用在 Android和其他等核心产品上,Skia 目前是Android 官方的图像渲染引擎,因此 Flutter Android SDK 无需内嵌 Skia 引擎就可以获得天然的 Skia 支持;而对于 iOS 平台来说,由于 Skia 是跨平台的,因此它作为 Flutter iOS 渲染引擎被嵌入到 Flutter 的 iOS SDK 中,替代了 iOS 闭源的 Core Graphics/Core Animation/Core Text,这也正是 Flutter iOS SDK 打包的 App 包体积比 Android 要大一些的原因。 底层渲染能力统一了,上层开发接口和功能体验也就随即统一了,开发者再也不用操心平台相关的渲染特性了。也就是说,Skia 保证了同一套代码调用在 Android 和 iOS 平台上的渲染效果是完全一致的。 Flutter架构 Framework底层是Flutter引擎,引擎主要负责图形绘制(Skia)、文字排版(libtxt)和提供Dart运行时,引擎全部使用C++实现,Framework层使我们可以用Dart语言调用引擎的强大能力。Flutter 架构采用分层设计,从下到上分为三层,依次为:Embedder、Engine、Framework。 Embedder 是操作系统适配层,实现了渲染 Surface 设置,线程设置,以及平台插件等平台相关特性的适配。从这里我们可以看到,Flutter 平台相关特性并不多,这就使得从框架层面保持跨端一致性的成本相对较低。 Engine 层主要包含 Skia、Dart 和 Text,实现了 Flutter 的渲染引擎、文字排版、事件处理和 Dart 运行时等功能。Skia 和 Text 为上层接口提供了调用底层渲染和排版的能力,Dart 则为 Flutter 提供了运行时调用 Dart 和渲染引擎的能力。而 Engine 层的作用,则是将它们组合起来,从它们生成的数据中实现视图渲染。 Framework 层则是一个用 Dart 实现的 UI SDK,包含了动画、图形绘制和手势识别等功能。为了在绘制控件等固定样式的图形时提供更直观、更方便的接口,Flutter 还基于这些基础能力,根据 Material 和 Cupertino 两种视觉设计风格封装了一套 UI 组件库,开发者可以直接使用这些组件库。 Flutter运行流程 页面中的各界面元素(Widget)以树的形式组织,即控件树。Flutter 通过控件树中的每个控件创建不同类型的渲染对象,组成渲染对象树。在Flutter界面渲染过程分为三个阶段:布局、绘制、合成,布局和绘制在Flutter框架中完成,合成则交由引擎负责。 Flutter 采用深度优先机制遍历渲染对象树,决定渲染对象树中各渲染对象在屏幕上的位置和尺寸。在布局过程中,渲染对象树中的每个渲染对象都会接收父对象的布局约束参数,决定自己的大小,然后父对象按照控件逻辑决定各个子对象的位置,最终完成布局过程。这里只需要注意一点,无论布局还是绘制,都是父子间的遍历关系:父Widget的布局需要依赖子Widget的布局结果;而绘制则反过来(子Widget需要盖在父Widget上),布局是后续遍历,绘制是前序遍历,他们都是深度优先遍历。 Flutter生命周期 可以看到,Flutter中State 的生命周期可以分为 3 个阶段:创建(插入视图树)、更新(在视图树中存在)、销毁(从视图树中移除)。接下来,我们一起看看每一个阶段的具体流程。 第一步创建 State 初始化时会依次执行 :构造方法 -> initState -> didChangeDependencies -> build,随后完成页面渲染。构造方法是 State 生命周期的起点,Flutter 会通过调用StatefulWidget.createState() 来创建一个 State。我们可以通过构造方法,来接收父 Widget 传递的初始化 UI 配置数据。这些配置数据,决定了 Widget 最初的呈现效果。 initState,会在 State 对象被插入视图树的时候调用。这个函数在 State 的生命周期中只会被调用一次,所以我们可以在这里做一些初始化工作,比如为状态变量设定默认值。 didChangeDependencies 则用来专门处理 State 对象依赖关系变化,会在 initState() 调用结束后,被 Flutter 调用。 build,作用是构建视图。经过以上步骤,Framework 认为 State 已经准备好了,于是调用 build。我们需要在这个函数中,根据父 Widget 传递过来的初始化配置数据,以及 State 的当前状态,创建一个 Widget 然后返回。 第二步更新 Widget 的状态更新,主要由个方法触发:setState、didchangeDependencies、didUpdateWidget。 setState:我们最熟悉的方法之一。当状态数据发生变化时,我们总是通过调用这个方法告诉 Flutter:“我这儿的数据变啦,请使用更新后的数据重建 UI!” didChangeDependencies:State 对象的依赖关系发生变化后,Flutter 会回调这个方法,随后触发组件构建。哪些情况下 State 对象的依赖关系会发生变化呢?典型的场景是,系统语言 Locale 或应用主题改变时,系统会通知 State 执行 didChangeDependencies 回调方法。 didUpdateWidget:当 Widget 的配置发生变化时,比如,父 Widget 触发重建(即父 Widget 的状态发生变化时),热重载时,系统会调用这个函数。一旦这三个方法被调用,Flutter 随后就会销毁老 Widget,并调用 build 方法重建 Widget。 第三步销毁 比如组件被移除,或是页面销毁的时候,系统会调用 deactivate 和 dispose 这两个方法,来移除或销毁组件。 Flutter生态圈及其常用框架 一项技术一个框架是否流行,最直观的体现就是它的生态圈是否活跃,下面列举了一些Flutter开发中常用的库工具。 参考文献 1、[Flutter原理与实践](https://tech.meituan.com/2018/08/09/waimai-flutter-practice.html) 少杰 2、[Flutter框架技术概览](https://flutter.dev/docs/resources/technical-overview) 3、[Flutter中文官网](https://pub.dartlang.org/flutter/) 4、[Flutter插件仓库](https://pub.dev/flutter/packages)

罗思雨 2020-02-27 11:47:50 0 浏览量 回答数 0

问题

【精品问答】python百大常见问题与答案详解

祖安文状元 2020-02-24 17:56:41 363 浏览量 回答数 1

问题

程序员报错QA大分享(1)

问问小秘 2020-06-18 15:46:14 8 浏览量 回答数 1

问题

网站技术职位之我见:报错

kun坤 2020-06-09 13:55:57 0 浏览量 回答数 1

问题

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:15 27612 浏览量 回答数 19

问题

【精品问答】Java必备核心知识1000+(附源码)

问问小秘 2019-12-01 22:00:28 870 浏览量 回答数 1
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 SQL审核 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 人工智能 阿里云云栖号 云栖号案例 云栖号直播