分类 默认分类 下的文章

  1. install packages

    yarn add mobx mobx-react-lite
  2. in ./tsconfig.json

    1. set compilerOptions.experimentalDecorators = true
    2. sometimes you need to close project and reopenit, otherwise, it might keep waring: Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.ts(1219)
  3. create file src/stores/CounterStore.ts

    import { action, makeObservable, observable } from "mobx";
    
    export class CounterStore {
      constructor() {
        makeObservable(this)
      }
      @observable
      value: number = 0;
    
      @action
      increment() {
        this.value += 1;
      }
    
      @action
      decrement() {
        this.value -= 1;
      }
    }
  4. create file src/stores/index.ts

    import React from "react";
    import { CounterStore } from "./CounterStore"
    
    export const stores = Object.freeze({
      counterStore: new CounterStore()
    })
    
    export const storesContext = React.createContext(stores);
    export const StoresProvider = storesContext.Provider;
  5. create file src/stores/hooks.ts

    import React from 'react'
    import { stores, storesContext } from "./";
    
    export const useStores = () => React.useContext(storesContext);
    
    export const useStore = <T extends keyof typeof stores>(
      store: T
    ): typeof stores[T] => React.useContext(storesContext)[store];
  6. in pages

    import { useEffect } from "react"
    import { useStore } from "../../stores/hooks"
    import { observer } from "mobx-react-lite"
    
    const MyPage = observer(() => {
      const counterStore = useStore('counterStore')
      useEffect(()=>{
        console.log(counterStore?.value)
      }, [counterStore?.value])
      return (
        <div>
          <p><button onClick={()=>counterStore.increment()}>increment</button></p>
          <p><button onClick={()=>counterStore.decrement()}>decrement</button></p>
        </div>
      )
    })
    export default MyPage

    reference: javascript.plainenglish.io/all-you-need-is-mobx-react-lite-47ba0e95e9c8

在oracle服务器上运行:

curl http://169.254.169.254/opc/v1/instance/definedTags/

返回示例:

{
  "Oracle-Tags": {
    "CreatedBy": "default/[email protected]",
    "CreatedOn": "2022-07-31T07:51:25.197Z"
  }
}

CreatedBy字段就是你的oracle账号
官方出处:docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm

假设你要把 www.baidu.com 301 到 baidu.com,需要以下2步操作:

1. page rules里

  • URL填写:www.nestjs.gay/*,开头不需要要http
  • Pick a Setting选择forwarding URL
  • destination URL填写 https://baidu.com/$1,填/$1的目的是为了保留转发的路径不变

2. DNS解析那里

  • 将www.baidu.com cname到www.cloudflare.com,并且勾选Proxied,当然也可以用A解析到某个cloudflare的ip上,没这个解析的话,301无法生效,解析到非cloudflare ip也无效,这就是坑

const whiteListSuffixs = [
  '*', // allow all domain suffix
]
async function handleRequest(request) {
  const urlReq = new URL(request?.url)
  let url = urlReq.href?.replace(urlReq.origin+'/', '').trim()
  if (!url) {
    return new Response(`error code 1, usage: ${urlReq.origin}/http(s)://api.example.com`, {status: 400})
  }
  if (0!==url.indexOf('https://') && 0===url.indexOf('https:')) {
    url = url.replace('https:/', 'https://')
  } else if (0!==url.indexOf('http://') && 0===url.indexOf('http:')) {
    url = url.replace('http:/', 'http://')
  }
  let urlTarget
  try {
    urlTarget = new URL(url)
  } catch(e) {
    return new Response(`error code 2, usage: ${urlReq.origin}/http(s)://api.example.com`, {status: 400})
  }
  if (urlTarget?.port) {
    return new Response('port is not allowed', {status: 400})
  }
  const hostname = urlTarget?.hostname
  if (!hostname) {
    return new Response(`error code 3, usage: ${urlReq.origin}/http(s)://api.example.com`, {status: 400})
  }
  let inWhiteList = false
  for (const suffix of whiteListSuffixs) {
    if (hostname.indexOf(suffix) > -1 || '*'===suffix.trim()) {
      inWhiteList = true
      break
    }
  }
  if (!inWhiteList) {
    return new Response( `${urlTarget.hostname} not in white list`, {status: 403} )
  }
  const response = await fetch(url, {
    headers: request.headers,
    body: request.body,
    method: request.method
  })
  let respHeaders = {}
  response.headers.forEach((value, key)=>respHeaders[key] = value)
  if ('*'!==respHeaders['Access-Control-Allow-Origin']?.trim() && '*'!==respHeaders['access-control-allow-origin']?.trim()) {
    respHeaders['Access-Control-Allow-Origin'] = '*'
  }
  return new Response( await response.body , {
    headers: respHeaders,
    status: response.status
  })
}
addEventListener('fetch', event => {
  return event.respondWith(handleRequest(event.request))
})

已知Bug:如果你反代带端口的url,例如http(s)://example.com:3000/path?query=string,它会自动去除端口再请求,变成请求http(s)://example.com/path?query=string

安卓

安卓很简单,用以下代码即可:

<WebView 
  source={{ uri: '包含支付宝的网页,例如有赞手机网页商城' }} 
  originWhitelist={["*"]} // default only http and https
  sharedCookiesEnabled={true}
  onShouldStartLoadWithRequest={navState => {
    if (0===navState.url.indexOf('alipays://') || 0===navState.url.indexOf('alipay://')) {
      Linking.openURL(navState.url)
      return false
    }
    return true // if not alipay scheme, just open
  }}
/>

其中安卓scheme是alipays://,iOS是alipay://

iOS/iPadOS

iOS的话,无法直接在Expo Go上测试支付宝支付,需要更改配置编译.ipa安装包
https://docs.expo.dev/guides/linking/#opening-links-to-other-apps
在./app.json里

"expo": {
  ... ...
  "ios": {
    "supportsTablet": true,
    "infoPlist": {
      "LSApplicationQueriesSchemes": ["alipay", "alipays"]
    },
    "bundleIdentifier": "com.yourdomain.yourproject"
  },
  ... ...
}

编译.ipa安装包并在iOS/iPadOS设备上安装运行的方式:https://medium.com/nerd-for-tech/abbde4086d08
备份文章:https://nftstorage.link/ipfs/bafybeidpjbd7ye5vfxa6vhsrjssfsk5qw6ib2kmnkkbe6lqd3qdrcakpym
上文用的是windows系统,如果你是Mac系统,USB连接iPhone后,可以在Finder左边栏里找到iPhone设备的界面,将.ipa安装包拖到这个界面即可安装到手机