(无任何网络配置,纯代码实现) 一个组件,一个hook,让你在本地开发环境中拿到微信code

前言

众所周知,初次接触微信相关生态铁定是头疼的,用微信API第一步就得拿到微信code, 官方上说这么操作,实际业务上体现就是:需要code的页面首先得重定向到微信的授权地址上面去,并且要携带上你当前项目的域名(redirect_uri)和AppId还有其他同样重要的参数(response_type、scope、#wechat_redirect、state等),授权成功后会重新重定向回你的域名上并为你的域名拼接上code。 至此一个code就到手了,能完成上面流程的代码和具体参数的意思一搜一大把,我这就不再赘述唠。今天要说的是本地开发环境中如何优雅(奇技淫巧)的获取微信code😆

痛点:痛!太痛了!

不用我说,大伙都知道,微信网页授权的过程中携带的redirect_uri,也就是你项目的域名必须在微信公众平台里配置为网页授权域名

实际开发中,我们至少得配置生产域名和测试域名。但真正糟心还是属本地环境下如何调试,如何去获得code, 我所知道市面上常用的法子是配置测试域名, 还有就是内网穿透。这两种方式配置都很麻烦,对于小白不是很有好。尤其后者对于没有网络基础的小白听着就有些劝退。

踩坑后的顿悟

自己刚开始接触到h5项目时,为了得到这个code,每次测试都自己部署到线上去测,只因为线上域名在公众号中配置过,也只有通过线上域名能拿到code。而且这样反复部署过于繁琐又非常不安全,太容易翻车。虽然通过配配置测试域名成功在本地拿到过code, 但后端同样需要配置,鉴定为麻烦,放弃!内网穿透,鉴定为搞不懂,放弃!😂

所以后面擅长放弃的我想了个办法,反正目的只是拿code, 用点下流(愚蠢)的手段又不是不可以:
首先我先在微信开发者工具中打开项目的线上地址,调慢网速,手动去把得到code扣下来,然后我再往我本地地址上面一复制,铛铛!完成!本地环境成功拿到了线上code!🤗

但实际这么操作几次,发现依旧蛋疼,code用一次就废了,新的code还要用上面的方式去获取一次。

所以有没有那么一种方式,不用我再手动去拿code, 再复制?也不去配置那些多余域名?也不用做那我还搞不懂的内网穿透?最好就用框架本身去解决?用js代码去解决?答案是可以的!🤩

以下是下流手段转化为优雅代码的过程

  1. 首先需要前往微信公众平台配置一个,合法的网页授权域名。(官网如是说)
  2. 开发一个名为传送门的组件,并将该组件挂载到前端路由上,如/portal,然后项目部署至刚才配置过的合法域名上;
  3. 接着封装一个useWxCode的hook, 它可以与传送门 相联动
  4. useWxCode在任何一个需要code的页面直接调用即可,生产环境下可以正常往微信授权网址跳转,并获取code,然后重定向回来。但在开发环境中,当向微信授权网址重定时,useWxCode将会带着当前本地Url作为参数往线上的传送门组件的路由上跳转。当跳到线上的传送门时code其实已经到手了,而传送门的唯一一项工作就是,将路径参数里的本地Url与code以及其他参数拼接起来作为重定向的路径并进行跳转。至此大功告成!😎

CAN CAN NEED CODE

我是在react中实现的,但主要都是以TS为主,其他任何框架稍微改改也能使用,废话少说,上代码:

传送门组件 (PortalComponent)

创建 portalComponent.tsx ,且为其注册路由。对应上面第二个步骤,

该组件的作用是:路径中存在code时,将路径参数里的本地Url与code以及其他参数拼接起来作为重定向的路径并进行跳转。

PortalPath 为传送门组件的 路由名 + ?,传送门组件与hook都会用到该参数参与路径拼接,所以建议写在公共配置文件中。

// portalComponent.tsx
const PortalPath = 'portal?';
export default function PortalComponent() {
  const code = React.useRef<string>(geUrlParam(location.href)?.['code']);
  React.useEffect(() => {
    if (code.current) {
      const hash = '#/';
      /* 微信授权地址上的redirect_uri进行了encodeURIComponent处理,
         所以这里必须使用decodeURIComponent进行解析。 */
      const originalUrl = decodeURIComponent(location.href.split(PortalPath)[1]);
      const redirectUrl = originalUrl.split(hash)[0] + `?code=${code.current}` + hash + originalUrl.split(hash)[1];
      window.location.href = redirectUrl;
    }
  }, []);
  // 返回空标签都行,但这里我用了个过渡的loading组件
  return <LoadingComponent />;
}
// route.ts
  {
    path: '/portal',
    component: () => import('./portal-component/portal.component'),
    lazyload: true,
    exact: true
  }

获取Url中参数的方法

function geUrlParam(search: string) {
    const param: Record<string, any> = {};
    search.replace(/([^&=?]+)=([^&]+)/g, (m, $1, $2) => (param[$1] = $2));
    return param;
 }

useWxCode (hook)

创建 useWxCode.ts 。对应上面第三个步骤

此hook,封装了自动获取微信code的逻辑代码,也暴露了code, wxLoading等状态, 以及刷新code的方法

export const PortalPath = 'portal?';

export const WxState = { wxLoading: true };

export interface WxCodeHookOpt {
  /** 拿到code后将重定向的前端路由,例如:login | login?a=123&b=456 */
  route: string;
  /** 拿到 code 后立即执行的方法 */
  getCodeAfterFn?: (code: string) => void;
  /** 是否页面初始化就跳转微信鉴权页面获取Code,默认:true */
  isPreGetCode?: boolean;
  /** WX授权方式 默认:snsapi_userinfo */
  scope?: 'snsapi_userinfo' | 'snsapi_base';
}

export interface WxCodeHookRes {
  /** 微信code */
  code: string;
  /** 刷新|获取 微信code */
  refreshCode: () => void;
  /** 获取wxCode时的loading状态 */
  wxLoading: boolean;
}

/** 在需要微信code的h5页面中使用 */
export function useWxCode(wxCodeHookOpt: WxCodeHookOpt): WxCodeHookRes {
  const [state, setState] = useState(WxState);
  const { wxLoading } = state;
  const { route, getCodeAfterFn, isPreGetCode = true, scope = 'snsapi_userinfo' } = wxCodeHookOpt;
  const code = useRef<string>();
  // 判断路径中是否已存在code,存在code,关闭wxLoading, 执行 getCodeAfterFn;
  // 不存在code, 通过isPreGetCode判断 是否需要自动获取code。
  useEffect(() => {
    code.current = geUrlParam(location.href.split('#/')[0])['code'];
    if (code.current) {
      setState({ wxLoading: false });
      getCodeAfterFn && getCodeAfterFn(code.current);
    } else {
      isPreGetCode ? refreshCode() : setState({ wxLoading: false });
    }
  }, []);

  // 刷新|获取 微信code
  function refreshCode() {
    // 开发环境会重定向到线上的[传送门]组件中获取code,获取code后再带着code返回源地址
    // 正式环境则直接跳微信授权网址获取code
    const noCodeUrl = location.href.split('?code=')[0] + location.hash;
    const devHref = code.current ? noCodeUrl : location.href;
    const devGetCodePath = PortalPath + devHref;
    const routePath = process.env.NODE_ENV === 'development' ? devGetCodePath : route;
    // process.env.REDIRECT_URL 就你的线上地址,也就你所配置的公众号合法的网页授权域名。
    const str = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${
      process.env.appId
    }&redirect_uri=${encodeURIComponent(
      process.env.REDIRECT_URL + routePath
    )}&response_type=code&scope=${scope}&state=123#wechat_redirect`;
    window.location.href = str;
  }

  return {
    refreshCode,
    code: code.current,
    wxLoading
  };

使用

在任何需要使用微信code的页面,直接调用 useWxCode 即可!暴露的 code, wxLoading, refreshCode ,可以满足你后续代码有关code的任何需求!

// xxx.tsx
const { code, wxLoading, refreshCode } = useWxCode({ route: 'home' });
// do anything ...

使用useWxCode后,开发环境会重定向到线上的[传送门]组件中获取code,获取code后再带着code返回源地址; 正式环境则直接跳微信授权网址获取code

效果

从此开发h5页面,只需配置一个公众号授权域名,无论测试环境,还是本地开发环境,只需添加如上代码,获取code,就是这么丝滑~

在这里插入图片描述

最后的最后

这里是萌新小把子,这是我第一篇技术文章,期待各位大佬狠狠的指点~!😆

好的,实现一个无限循环的React函数组件轮播器,不使用任何hook和轮播UI库,可以按照以下步骤进行: 1. 创建一个React函数组件,命名为Carousel。 2. 在组件内部使用useState hook来管理state,包括图片数据、当前图片的索引、轮播定时器等。代码如下: ``` import React, { useState, useEffect } from 'react'; function Carousel() { const [images, setImages] = useState([ { id: 1, src: 'image1.jpg' }, { id: 2, src: 'image2.jpg' }, { id: 3, src: 'image3.jpg' }, { id: 4, src: 'image4.jpg' }, { id: 5, src: 'image5.jpg' }, ]); const [currentIndex, setCurrentIndex] = useState(0); const [timer, setTimer] = useState(null); useEffect(() => { const timer = setInterval(() => { handleNext(); }, 3000); setTimer(timer); return () => clearInterval(timer); }, [currentIndex]); const handleNext = () => { const nextIndex = currentIndex === images.length - 1 ? 0 : currentIndex + 1; setCurrentIndex(nextIndex); }; const handlePrev = () => { const prevIndex = currentIndex === 0 ? images.length - 1 : currentIndex - 1; setCurrentIndex(prevIndex); }; const prevIndex = currentIndex === 0 ? images.length - 1 : currentIndex - 1; const nextIndex = currentIndex === images.length - 1 ? 0 : currentIndex + 1; return ( <div className="carousel"> <div className="carousel-images"> <img src={images[prevIndex].src} alt="prev" /> <img src={images[currentIndex].src} alt="current" /> <img src={images[nextIndex].src} alt="next" /> </div> <div className="carousel-buttons"> <button onClick={handlePrev}>Prev</button> <button onClick={handleNext}>Next</button> </div> </div> ); } export default Carousel; ``` 3. 在CSS设置轮播图片的样式,包括绝对定位、宽度、高度等。代码如下: ``` .carousel-images { position: relative; width: 100%; height: 400px; } .carousel-images img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; } .carousel-images img:nth-child(2) { z-index: 1; } .carousel-images img:first-child { z-index: 2; transform: translateX(-100%); } .carousel-images img:last-child { transform: translateX(100%); } ``` 这样就完成了一个简单的React函数组件无缝滚动轮播器的实现。注意,由于函数组件没有生命周期方法,因此使用了useEffect hook来启动轮播定时器和清除定时器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值