Admin 发布的文章

React Native Webview组件没有自带的方式可以监听网页内部资源的加载(jpg, png, js, css, mp3等),曲线实现方式:用js注入定时器到网页,网页里获取节点的src属性并postMessage给native,以img节点为例:

import { WebView } from 'react-native-webview'
let srcs:string[] = []
export default function WebviewScreen() {
  return (
    <WebView 
      source={{ uri: 'https://www.bing.com/images' }}
      useWebKit={true}
      allowsBackForwardNavigationGestures
      allowsInlineMediaPlayback
      injectedJavaScriptBeforeContentLoaded = {`
        setInterval(()=>{
          const nodes = document.querySelectorAll('img')
          for (const node of nodes) {
            window.ReactNativeWebView.postMessage(node.src)
          }
        }, 2000)
      `}
      onMessage = {msg=>{
        const src = msg.nativeEvent?.data?.trim()
        if (src && -1===srcs.indexOf(src)) {
          console.log('onMessage', new Date(), src)
          srcs.push(src)
        }
      }}
    />
  );
}

也可以用于video等其它带有src的节点
如果是video,src可能在它的子节点srouce里,而且可能有多个,所以需要这么写:

setInterval(() => {
  const videoElems = document.querySelectorAll('video')
  for (const videoElem of videoElems || []) {
    window.ReactNativeWebView?.postMessage(videoElem.src)
    for (const courceElem of videoElem.getElementsByTagName('source') || []) {
      window.ReactNativeWebView?.postMessage(courceElem.src)
    }
  }
}, 1000)

缺点:

  1. 只能定时不能监听
  2. 如果网页里用到跨域的iframe,则iframe里的resource无法被获取

  1. 很多时候,input只关心最后状态,不需要用useState
    请输入图片描述
  2. 有时候并不需要用useEffect去改变值
    请输入图片描述
  3. useMemo防止object在重新渲染时再内部值不变时被更换内存地址,变成新“值”
    请输入图片描述
  4. 适时终止过时的api请求
    请输入图片描述

  1. Add custom.d.ts to ./scr

    declare module '*.svg' {
      import React = require('react')
      export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>
      const src: string
      export default src
    }
  2. Import svg on your page

    import { ReactComponent as IconLogo } from '../assets/images/logo.svg'
  3. Usage

    <IconJolt height='10' />

前端在调用别人 api 时经常遇到跨域或者 https 无法调用 http 的问题,通过反代即可解决
deno.com 提供免费的 NodeJS 环境,在其官网后台新建应用,在 playground 粘贴代码:

import { serve } from "https://deno.land/[email protected]/http/server.ts"
serve(async (req: Request) => {
  const url = new URL(req.url)
  const targetUrl = url.href.replace(`${url.origin}/`, '')
  let urlObj: any
  try {
    urlObj = new URL(targetUrl)
  } catch (e) {
    console.error(e.message)
  }
  if (['http:', 'https:'].indexOf(urlObj?.protocol) > -1) {
    let res = await fetch(targetUrl, {
      headers: req.headers,
      method: req.method,
      body: req.body,
    })
    let headers = {}
    res.headers.forEach((value, key) => {
      headers[key] = value
    })
    if ('*' !== headers['Access-Control-Allow-Origin']?.trim()
      && '*' !== headers['access-control-allow-origin']?.trim()) {
      headers['Access-Control-Allow-Origin'] = '*'
    }
    return new Response(res.body, { headers, status: res.status })
  }
  return new Response(
    `Usage: ${url.origin}/https://deno.com/deploy/docs/pricing-and-limits`)
})

优势:跟cloudflare worker相比,这个支持带端口的url