h5逻辑_H5+app 混合开发

2023-11-15

app分类

app主要指的是在手机上运行的第三方应用程序~主要分为一下三类

  • Native App (原生应用):指的是基于手机操作系统开发出来的第三方应用程序
    • 需要下载(每次更新都需下载)
    • ios/android 操作系统不同,代码不兼容(需要开发两套不同的代码) -> 开发慢,开发成本高
    • 用户体验度好
  • Web App(网页应用):指的是使用web技术来开发的app
    • 不需要下载
    • 跨平台的,一套代码可以在多个浏览器使用->开发快、快发成本低
    • 用户体验不太好,不同的浏览器展示效果可能存在差异,部分功能无法实现
  • HyBird App(混合应用)
    • 将原生应用与网页应用相结合,集原生应用 与 网页应用的优点于一身
    • 本质就是将web页面内嵌在原生app中,然后产生一系列的交互~

h5与原生进行交互

[1] 判断h5页面打开的环境是ios/android

通过navigator.userAgent判断当前页面的运行环境

[2] JS与客户端互相调用
js调用ios的方法
  • 在ios中:在ios中定义的方法若是想被嵌入的h5页面调用

    • [1] 声明一个方法 如getAppInfo
    • [2] 注册对这个方法的监听
        wkWebView.configuration.userContentController.add(self, name: getAppInfo)
      
  • 在js中

    在js中使用固定语法进行调用window.webkit.messageHandlers.方法名.postMessage(传参数据)

    window.webkit.messageHandlers.getAppInfo.postMessage()
    
js调用android的方法
  • 在android中

    在android中,需要暴露出一个全局变量xxxBridge,类似浏览器环境中的Window

      // 获取webview的设置对象
      WebSettings webSettings = mWebView.getSettings()
      //  设置Android允许js脚本
      webSettings.setJavaScriptEnabled(true)
      // 暴露出JSBridge的对象到webView的全局环境
      mWebView.addJavascriptInterface(getJSBridge(), 'JSBridge')
    

    嵌入的web页面中就多了一个全局变量JSBridge,通过此全局变量可以调用android客户端的方法或属性啦。

  • 在js中

    在js中的调用是非常简单的,比如说在android中暴露的全局变量名为JSBridge,该变量上存在getAppInfo方法, 通过如下代码即可调用

      Window.JSBridge.getAppInfo()
    
error- android接收不到参数
window.JSBridge.showShareIcon({
  id: 1,
  type: 1
})

我按照如上方式进行传参,客户端是接收不到的,客户端要求直接传两个参数,参数类型都为简单数据类型,如下:

window.JSBridge.showShareIcon(11)

这样就可以正常接收啦。

h5调用android的方法时传递的参数必须为简单数据类型

js调用ios与android的区别
  • 调用ios的方法时是异步的;而调用android的方法时是同步的!
  • 调用ios方法传参时可以传对象;而调用android的方法时只能传简单数据类型!
示例:js调用ios与android完整示例代码
function info() {
  if (navigator.userAgent.search(/(iphone|ipad|ipod)/i) >= 0) {
     return 'iOS' // 手机iOs
  } else if (navigator.userAgent.search(/android/i) >= 0) {
    return 'Android' // 手机安卓
  } else if (navigator.userAgent.search(/windows phone/i) >= 0) {
    return 'WinPhone'
  } else {
    return 'PC'
  }
}
const platform = info()
const params = {...}
if (platform === 'iOS' && window.webkit) {
// showShareIcon 为ios抛出的方法
 window.webkit.messageHandlers.showShareIcon.postMessage(params)
} else if (platform === 'Android' && window.JSBridge) {  
  // JSBridge为Android抛出的全局对象
  window.JSBridge.showShareIcon(JSON.stringify(params))
}else {
  return false
}
客户端调用js方法

若是客户端想调用web页面中的方法,需要我们先将方法暴露出去

tips: 有时客户端拿不到window, 因此需要做下兼容~

const pluginFun = (function(){
  // 兼容全局对象
  const _global = (function () {
    return window || this
  }())
  const plugin = {
    方法1(){},
    方法2(){},
    ...
  }
  // 将和客户端约定的方法暴露给全局对象
  for (const i in plugin) {
    !('jsFunc' in _global) && (_global[i] = plugin[i])
  }
}())
示例: 客户端与web交互之回调

需求场景:web页面上有提现功能,此功能的逻辑是

  • [1] 用户在h5页面点击提现
  • [2] h5调用客户端方法(客户端调用支付宝支付通道判断是否可以提现),判断结果返回到web页面
  • [2] web页面获取到是否可以提现之后:若是可以提现调取提现接口,若是不可以提现则提示不可提现原因;

在vue中可以使用$on进行事件监听,具体做法如下

  • [1]调用客户端isDrawal方法->判断是否可以提现并监听客户端返回结果
    created(){
      vm.$on('drawal', data=>{
        // 获取到客户端返回的信息data, 若是可以提现则调取提现接口,若是不可以提现则提示不可提现原因;
      })
    }
    methods:{
      isDrawal(){
        if(isAndroid && window.JSBridge){
          window.xxxJSBridge.isDrawal(url) // url是支付宝url
        }
      }
    }
    
  • [2] 封装callbackme方法供客户端调用
    const pluginFun = (function(){
      // 兼容全局对象
      const _global = (function () {
        return window || this
      }())
      function callbackme(data){
        vm.$emit('drawal', data)
      }
      _global.drawal = callbackme
    }())
    
[3]页面跳转

vue项目中正常的页面跳转代码如下

this.$router.push(url)

当代码执行之后将在原来的浏览器窗口中打开该页面。

客户端嵌入的web页面在进行跳转时可能跳转到客户端页面也有可能跳转到其他h5页面。

此时引入了一个新的概念webView

webView

webView可以看作是本地应用程序内嵌的一个浏览器,它拥有渲染引擎,可以通过http/https请求加载内容,加载回来的代码就可以被执行和渲染。

web端与客户端约定协议

当web页面嵌入客户端时,需要约定一个跳转协议,假设约定的协议名为bd-triger

  • 跳转到h5页面
    // url为要跳转的h5页面的全路径
    jumpPage(url){
      location.href = 'bd-triger://web?url='+encodeURIComponent(url)
    }
    
  • 若是要跳转到客户端内的页面
    location.href='bd-triger://客户端提供的页面名'
    

那么问题来了—> 嵌入客户端的页面还能使用原本的方法($router.push)进行页面跳转吗?

答案是可以的!

  • 若是使用$router.push等方法去进行页面跳转时,该页面会在当前webView(相当于是同一个浏览器)中打开。

  • 若是使用h5与客户端预先约定的协议进行页面跳转时,则该页面会在新的webView(新的浏览器页面)中打开。

听起来好像是没有很大区别,但是问题的本质是在同一个webView打开的页面状态一致(以第一个页面为准),如是否全屏,是否监听控制页面跳转等等....

是否全屏打开页面

在这里插入图片描述
一个完整的页面包含 状态栏+导航栏+内容部分。

  • 若是全屏显示,则web页面的嵌入面积包含这三部分的面积(tips: 此时需要自己设置page padding-top 防止内容和状态栏重叠)
  • 若是非全屏显示,则web页面的嵌入面积仅有内容content部分,页面自带客户端的导航栏和状态栏间距。

页面全屏/非全屏展示

在客户端中分为一级页面和二级页面。在客户端中一般情况下存在几个tab页面,tab页面就是一级页面,由一级页面跳转进入二级页面。

一级页面(tab页面)默认为全屏展示,若是h5页面作为tab页面嵌入,那么就必须设置好状态栏的高度,否则样式就会混乱!

若是二级页面则可以和客户端约定一个路径参数来判断当前web页面是否需要全屏展示(能不用全屏就不用全屏)。

若是需要全屏展示,还有一个新的问题,那就是状态栏高度(设置padding防止页面与状态栏重叠)

  • 若是ios的状态栏高度可以通过css参数直接设置
  • 若是android的状态栏高度在h5页面是直接获取不到的,需要客户端获取传递。此时需要再和客户端约定一个路径参数(若是全屏客户端在路径上拼接此参数)。

举例说明:假设和客户端约定的是否全屏参数为need_full_screen,状态栏高度为height,那么

  • 全屏展示
    'bd-triger://web?url='+encodeURIComponent('http://xxx?need_full_screen=1&height=40')
    
  • 非全屏展示
    'bd-triger://web?url='+encodeURIComponent('http://xxx')
    

跳转

在同一个webView打开的页面是否全屏 设置相同并且以第一个页面为准!

举例说明

  • [1] 假设存在h5页面page1,该页面嵌入在tab页面(默认全屏);在page1中存在按钮“支付”,点击跳转到支付页面(h5页面),此时存在以下几种情况
    • 情况1
      this.$router.push('/web/pay') 
      
      此时页面在当前webView打开,该webView第一个页面为page1(全屏),因此支付页也为全屏打开
    • 情况2
        location.href = 'bd-triger://web?url='+encodeURIComponent(`${location.origin}/web/pay`)
      
      此时页面在新的webView打开,双方约定的是否全屏参数值为false,因此支付页为非全屏打开
    • 情况3
       location.href = 'bd-triger://web?url='+encodeURIComponent(`${location.origin}/web/pay?need_full_screen=1`)
      
      此时页面在新的webView打开,双方约定的是否全屏参数值为ture,因此支付页为全屏打开
  • [2] 支付页面存在弹框提示“是否支付成功”,若是支付成功跳转到h5页面订单列表页面,此时的页面跳转也存在以下情况(情况1-3分别对应[1]中的1-3)
    • 情况1
      this.$router.push('/web/orderlist') 
      
      是否全屏只和当前webView的第一个页面有关,因此看page1(默认全屏),因为订单列表页也为全屏打开
      • 情况2
        location.href = `bd-triger://web?url=${location.origin}/web/orderlist`
        
        在新的webView打开的页面是否全屏和上一级无关,只看路径携带参数,路径没有携带参数,因此订单列表页为非全屏打开。
        • 情况3
        location.href = 'bd-triger://web?url='+encodeURIComponent(`${location.origin}/web/orderlist?need_full_screen=1`)
        
        在新的webView打开的页面是否全屏和上一级无关,只看路径携带参数,路径携带参数need_full_screen为true,因此订单列表页为全屏打开。

总结

当使用bd协议去打开页面时若是设置全屏(非全屏),则在当前webview中再打开其他页面都是全屏(非全屏)直至再次使用bd协议在新的webView去打开页面。

返回

和跳转相同,返回在vue中也存在自己的方法this.$router.back()

在同一个webView内进行页面跳转

this.$router.push(url)

当点击返回按钮时可以使用自己的返回方法

this.$router.back()

当打开一个新的webView进行跳转时,可以想成重新打开一个浏览器页面进行跳转(a标签设置target属性值为_blank)。

location.href = bd-triger+ '://web?url=' + encodeURIComponent(url)

但是此时点击返回按钮不能使用back方法了(因为现在打开的是一个全新的窗口栈,里面没有之前的跳转记录)。

在返回时也不能判断前面有没有已经打开的webView,因此自己的返回方法在混合开发中不能使用

客户端获取的浏览栈记录是全的,只需要和客户端协商方法,当用户点击“返回”按钮时调用客户端方法即可。

// 假定约定方法名为back
window.xxxJSBridge.back()
返回-禁止返回

用户可能通过 导航栏的返回按钮、左滑、手机下方的操作按钮返回到上一页面。

但是有时用户点击返回按钮,我们并不期望用户返回上一级而是期望挽留一下用户。

举例说明: 吸引用户到开通会员页面以99.9的价格开通会员,若是用户不想购买返回上一级,我希望在用户有“返回”这个动作时,给用户来一个挽留弹框,表示现在购买价格为89.9(以一个优惠的价格吸引用户购买)。

此时需要禁止返回操作功能并监听用户返回—>其实客户端可以监听用户退出页面的情况,无论用户以何种方式退出页面客户端都可以监听到并且可以禁止用户退出页面

示例

在当前页面做挽留弹窗

  • [1] 在进入页面时调用客户端方法,禁止用户退出页面;

  • [2] 在进入页面时监听用户退出操作,并挽留

    • 当用户退出页面时就会被客户端监听到,客户端会调用H5页面的方法。
    • H5页面监听此方法是否被调用,并作出操作。
  • [3] 当挽留次数为0时,调用客户端方法取消用户禁止返回操作并返回

  • 准备:注册监听并挂在到全局

    import Vue from 'vue'
    export default const wBus = new Vue()
    
    Vue.prototype.wBus = wBus
    

    暴露出去监听方法,方便客户端调用

    function callback(data){
      this.wBus.$emit('back', data)
    }
    
  • 当前页面

    // [1][2]
    created(){
      // [1] start开始禁止返回
      window.PlayLetJSBridge.start()
      // [2] 监听用户返回操作
      this.wBus.$on('back', () => {
        this.onClickLeft()
      })
    }
    
     onClickLeft () {
        if(超过挽留次数){
        // 结束禁止返回
        window.PlayLetJSBridge.end()
        // 返回
        window.PlayLetJSBridge.back()
        }else{
          // 执行挽留逻辑
        }
    }
    
  • 打开app内的login页面(客户端页面)

error-没有结束禁止返回

需求
在当前页面page1无论以何种返回方式进行返回,都跳转至挽留页面(/retention),当在挽留页面点击返回时再返回上一级页面。

实现

  • 当前页面
    created(){
      window.PlayLetJSBridge.start()
      this.wBus.$on('back', () => {
        this.onClickLeft()
      })
    }
    onClickLeft () {
      this.$router.replace('/retention') // 替换掉当前栈
    }
    
  • 挽留页面
    // 返回方法
    onBack(){
      window.PlayLetJSBridge.back()
    }
    

效果
进入page1,点击返回按钮进入挽留页面没有问题,但是在挽留页面点击返回按钮就会报错。

原因
在进入挽留页面时没有打开新的webView,在同一个webView中的状态相同!,也就是说在page1页面禁止用户返回之后,在挽留页面的状态也是禁止用户返回的!

修改

 onClickLeft () {
  window.PlayLetJSBridge.end()
  this.$router.replace('/retention') // 替换掉当前栈
 }
返回-生命周期

如果是使用$router.push方法进行跳转,那么返回没有任何问题。
但是若是使用约定协议进行跳转,那么相当于当前页面没有被关闭,当点击返回按钮时不会重新进行初始化(不会走beforeCreate,created,beforeMount, mounted),当然重新跳转是没有问题的

生命周期-将h5页面作为客户端的tab页面

web页面作为客户端的tab页,切换tab的时候并不会销毁页面,也就是说再次打开页面的时候并不会走created生命周期函数(等同于上面的返回页面),导致数据不刷新(不是最新状态)。此时可以走回调函数解决问题

  • [1] 封装一个监听函数供客户端调用
    import Vue from 'vue'
    export default const wBus = new Vue()
    
    Vue.prototype.wBus = wBus
    
    const fun = function(){
      const _global = (function () {
        return  window || this
      }())
      const plugin = {
        function callback(data){
          this.wBus.$emit('refresh', data) // 哪里使用去哪里出发,此处统一封装
        }
      }
      for (const i in plugin) {
        !('jsFunc' in _global) && (_global[i] = plugin[i])
      }
    }()
    
  • [2] 在需要刷新的tab页面监听refresh方法
    vm.$on('refresh', (data)=>{
      if(data === 'refresh'){
        //  重新调去接口
      }
    })
    
[4] 在web页面下载app

下载地址是客户端给我们的(android与ios下载地址不同),因此在下载之前需要先判断浏览器的所属环境

if(navigator.userAgent.search(/(iphone|ipad|ipod)/i) >= 0){
  // ios
  location.href = 'xxx'
}else if(navigator.userAgent.search(/android/i) >= 0){
  // Android
   location.href='xxx.apk'
}else{
  // 跳转到应用宝下载
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

h5逻辑_H5+app 混合开发 的相关文章

  • Android 通知进度条冻结

    这是我正在使用的代码 http pastebin com 3bMCKURu http pastebin com 3bMCKURu 问题是 一段时间后 文件变得更重 通知栏下拉速度变慢 最后它就冻结了 你的通知太频繁了 这就是它冻结的原因 让
  • Android第一次动画不流畅

    我正在尝试一个动画将 imageView 从屏幕底部滑动到屏幕中心 但是当我第一次执行此动画时 它不平滑 但当第二次执行动画时 它是正常且平滑的 我几乎尝试了所有方法 但无法解决我的问题 这是我的动画文件
  • 如何从 SQLite 获取记录总数

    我正在尝试从 Sqlite DB 获取行的总数 以下是我想要做的代码片段 我不知道我在这里做错了什么 public static int getTotalCount Context context Cursor c null try c g
  • 如何查找 Android 设备中的所有文件并将它们放入列表中?

    我正在寻求帮助来列出 Android 外部存储设备中的所有文件 我想查找所有文件夹 包括主文件夹的子文件夹 有办法吗 我已经做了一个基本的工作 但我仍然没有得到想要的结果 这不起作用 这是我的代码 File files array file
  • Android 原理图内容提供程序库配置?

    Jake Wharton 在最近的一次演讲中提到了这个库 它看起来是避免大量样板文件的好方法 所以我尝试了一下 但没有任何成功 https github com SimonVT schematic https github com Simo
  • 更新到材质 1.2.0 后,材质按钮上缺少圆角半径属性

    这是我的材质按钮代码
  • OnClick 事件中的 finish() 如何工作?

    我有一个Activity一键退出Activity 通过layout xml我必须设置OnClick事件至cmd exit调用 this finish 效果很好 public void cmd exit View editLayout thi
  • 应用程序未安装在 Android 模拟器上

    我正在 android Geocoder 中开发一个应用程序 当我运行该应用程序时 它会显示 2011 01 11 11 08 13 GeoTourProject 自动目标模式 使用现有模拟器 emulator 5554 运行兼容的 AVD
  • Android 版 Robotium - solo.searchText () 不起作用

    我在使用 Robotium 时遇到 searchText 函数问题 我正在寻找这个字符串
  • 在 Jetpack Compose 中启动动画矢量 Drawable

    我有一个动画矢量可绘制R drawable my anim 我想在 Jetpack Compose 中展示并开始 可绘制对象显示 渲染正确 但动画未启动 这是撰写视图 Composable fun SplashView Surface mo
  • Flutter 深度链接

    据Flutter官方介绍深层链接页面 https flutter dev docs development ui navigation deep linking 我们不需要任何插件或本机 Android iOS 代码来处理深层链接 但它并没
  • Android 启动器快捷方式

    我制作了一个简单的打卡 打卡时钟应用程序 我想向用户添加在主屏幕上创建快捷方式的选项 该快捷方式将切换应用程序的状态 超时 超时 但我根本不希望此快捷方式在屏幕上打开应用程序 这是我的 setupShortcut private void
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • 检查 Android 手机上的方向

    如何查看Android手机是横屏还是竖屏 当前配置用于确定要检索的资源 可从资源中获取Configuration object getResources getConfiguration orientation 您可以通过查看其值来检查方向
  • Android相机意图:如何获取全尺寸照片?

    我正在使用意图来启动相机 Intent cameraIntent new Intent android provider MediaStore ACTION IMAGE CAPTURE getParent startActivityForR
  • Android Studio:无法启动守护进程

    当我尝试在 Android Studio 中导入 gradle 项目时 遇到以下错误 Unable to start the daemon process This problem might be caused by incorrect
  • 材质设计图标颜色

    应该是哪种颜色 暗 材质图标 在官方文档上 https www google com design spec style icons html icons system icons https www google com design s
  • 调节麦克风录音音量

    我们正在尝试调整录音时的音量级别 麦克风似乎非常敏感 会接收到很多静电 我们查看了 setVolumeControlStream 但找不到传入其中来控制麦克风的流 将您的音频源设置为 MIC using MediaRecorder Audi
  • 通过 ADB 拔出设备:“找不到服务”

    我必须测试我的应用程序在打瞌睡模式下的行为 根据文档 https developer android com training monitoring device state doze standby html testing doze 我
  • 如何将图像从 Android 应用程序上传到网络服务器的特定文件夹中

    如何将图像从 android 移动到 Web 服务器上的指定文件夹 这是我的安卓代码 package com example bitmaptest import java io ByteArrayOutputStream import ja

随机推荐

  • day24第三阶段总结

    day24 三阶段总结 课程目标 对第三模块 阶段的知识点进行总结和考试 更好的掌握此模块的相关知识 课程概要 知识补充 阶段总结 思维导图 考试题 1 知识点补充 1 1 并发编程 网络编程 从知识点的角度来看 本身两者其实没有什么关系
  • RS232 485 CAN端口浪涌、脉冲保护电路

    常见端口保护电路记录 实现保护等级 如果需要更高的防护等级需要其他电路配合 由于工作比较忙 有时候查起来太麻烦了 特此记录一下方便查询 模块评估版实物图 实现的保护等级如下 下面是zlg的rsm232完整保护电路 各个器件截图 GDT 气体
  • 使用httpclient 请求报错 :Software caused connection abort: recv failed

    Software caused connection abort recv failed java net SocketException Software caused connection abort recv failed at ja
  • DVWA靶场在sql注入联合查询时返回报错信息 “Illegal mix of collations for operation ‘UNION’ ”之解决

    比如我们输入 1 union select 1 table name from information schema tables where table schema dvwa 会跳出一个页面出现报错提示 Illegal mix of c
  • Form表单、四种常见的POST请求提交数据方式、MIME【转】

    浏览器行为 Form表单提交 1 form表单常用属性 action url 地址 服务器接收表单数据的地址 method 提交服务器的http方法 一般为post和get name 最好好吃name属性的唯一性 enctype 表单数据提
  • 浅析安全框架-Shiro和Spring Security

    一 权限概述 1 什么是权限 权限管理 一般指根据系统设置的安全策略或者安全规则 用户可以访问而且只能访问自己被授权的资源 不多不少 权限管理几乎出现在任何系统里面 只要有用户和密码的系统 权限管理分类 访问权限 管理员有增删改查权限 普通
  • 令AxosoftPowerTrack支持中文

    AxosoftPowerTrack是个有意思的vs netAdd in
  • javaweb实现一个账号只能同时被一个人使用(Java实现)

    大家在登陆qq的时候 电脑上登陆了qq 如果另一台机器上也登陆该qq账号 那么之前的qq账号会被挤下去 我们现在用web的方式来做一个非常简单的演示 先简单的说一下功能吧 用户只有一个User 这个entity设置成账号为hello 密码w
  • Web.xml加载顺序

    文章目录 Tomcat 加载顺序 Web xml具体加载顺序 Tomcat Server处理一个http请求的过程 lt context param gt lt listener gt lt filter gt web xml中定义的元素
  • 阿里云移动推送的接入和踩坑

    近期由于业务需求 要换掉以前的推送 首先选择了阿里云推送 官方介绍阿里移动推送 Alibaba Cloud Mobile Push 是基于大数据的移动智能推送服务 帮助App快速集成移动推送的功能 在实现高效 精确 实时的移动推送的同时 极
  • Elasticsearch 架构解析与最佳实践

  • 基于Docker如何快速部署自己的ChatGPT

    背景 随着OpenAI在2022年底发布的LLM模型 ChatGPT展现出的强大效果 ChatGPT无疑成为了当下炙手可热的明星模型 现有的基于GPT的开源项目已经非常多 本文以现有的高热度github开源项目chatgpt web为例 教
  • 利用宏简化Q_PROPERTY动态属性的定义

    目录 写在前面 实现历程 传统定义方式 预想的方式 事实上有一点点区别 测试通过的例程 mainwindow h mainwindow cpp main cpp 执行结果 Qt6 更新 写在前面 上一篇写了pyqt如何更加便利地定义动态属性
  • 【Unity VR开发】VRTK 3.3.0 配置与基本使用

    VRTK3 3 开发日志 2021 11 16更新 半年前第一次接触VR开发 看B站Siki学院的视频做的笔记 今天整理一下 以供没接触过VR开发的人来学习 有些地方没有配图 但个人认为影响不大 按文字说明一步步来操作还是没问题的 笔记参考
  • Python 和Java 哪个更适合做自动化测试?

    很多小伙伴工作在功能测试行业工作了2 3年后 发现自己已经把功能测试做的非常好了 已经到职业发展和薪资发展的瓶颈期了 就想着学点东西 提提升一下技能 而对于功能测试升级来说 一般有这么3个主流的发展方向 一是性能测试 一是接口测试 一是自动
  • 奶酪【BFS】

    题目链接 点从z 0为起点 想跑到z h 只能在球内 或者是球表层上跑 问能否从起点跑到终点 直接暴力bfs判断即可 include
  • linux下nodejs依赖库libuv库,开发环境准备

    nodejs底层使用libuv库实现异步IO 如果对nodejs的回调函数习以为常 而不知libuv 那岂不是很遗憾 libuv在github上托管了自己的源码 但是我要学习的是希望适用于nodejs某一个版本的 这样的代码是可以经过简单处
  • 华为OD机考攻略一文了解!最新岗位带你起飞

    了解透了华为OD是什么 准备好投递动作了 那就来看看整体的推进流程吧 一般经过 机考 线上 技术面试2轮 资格面试 1轮 综合面试 1轮 全程线上搞定全流程 对于异地的朋友很友好 机考准备之后 其他面试都在一周内完成 所以机考的准备尤为重要
  • 网络志愿者微公益行

    活动中 网络志愿者将书包和牛奶作为新年礼物送给孩子们 并走到愿望墙 一对一完成孩子们的小小愿望 发动仪式完毕后 网络志愿者深化贫困学生家中 详细了解他们的生活困难 并活跃协助处理
  • h5逻辑_H5+app 混合开发

    目录 app分类 h5与原生进行交互 1 判断h5页面打开的环境是ios android 2 JS与客户端互相调用 js调用ios的方法 js调用android的方法 error android接收不到参数 js调用ios与android的