最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端代码经常见到的 Provider 究竟是什么

    正文概述 掘金(zxg_神说要有光)   2021-08-08   479

    不知道你有没有在某处见过 xxProvider,Provider 并不是 23 种经典设计模式之一,但是却应用特别多,可以算是一种比较新的模式。

    • Angular2 中提供了创建对象的时候基于 Provider
    • VSCode 插件中有各种 registerXxxProvider 的 api
    • React 提供了 Provider 组件用于 context 数据的传递

    还有很多别的地方也经常会见到 Provider 的概念,那么 Provider 究竟是什么呢?

    本文就来回答下这几个问题:

    • provider 是什么
    • provider 创建对象和 factory 有什么区别
    • provider 的具体应用

    provider 是什么

    provider 是提供者,从名字上和设计模式中创建对象的那些模式很像,比如工厂方法模式,但其实两者是有区别的。

    工厂方法模式是用于创建不同的产品,通过继承的方式。

    前端代码经常见到的 Provider 究竟是什么

    但有的时候创建的对象可能有别的来源,比如从别的地方获取的一个值,或者已经创建好的对象。这时候来源就不只有工厂了。

    也就是说这时候要创建的对象有多种策略,工厂只是其中一种,策略 + 工厂/其他方式就是 Provider。

    前端代码经常见到的 Provider 究竟是什么

    provider 被微软引入到了 .net 2.0,而且微软其他的一些技术产品也随处可以见 provider,比如 VSCode 的 xxxProvider、angular2 的 providers。

    我们来看一些具体的应用。

    provider 的具体应用

    VSCode 插件的 provider 系列 api

    VSCode 插件中最常见的 api 就是 registerXxxProvider,通过该 api 注册的 Provider 就是实现了 provideXxx 的对象。

    比如智能补全就是注册一个 CompletionProvider,然后根据 document 的内容,返回具体的 CompletionItem 的对象。

    因为 VSCode 并不关心 CompletionItem 是怎么创建出来的,只知道通过这个 provider 可以拿到需要的 completion 数据,所以设计了 provider 的 api。

    const provider = vscode.languages.registerCompletionItemProvider(
            'plaintext',
            {
                    provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
                            return [
                                    new vscode.CompletionItem('log', vscode.CompletionItemKind.Method),
                                    new vscode.CompletionItem('warn', vscode.CompletionItemKind.Method),
                                    new vscode.CompletionItem('error', vscode.CompletionItemKind.Method),
                            ];
                    }
            },
            '.'
    );
    
    context.subscriptions.push(provider);
    

    React 中的 context 的 Provider

    react 组件树可以在父组件放一些数据到 context 中,然后子组件取出来用,也是通过 provider 的方式。

    父组件的作为 Provider 需要实现 getChildContext 方法,返回具体的对象。就像上面的 provideXxx 一样,react 并不关心这个对象是怎么来的。

    父组件里提供 getChildContext 提供数据

    class Ancestor extends React.Component {
      getChildContext() {
        return { value1: "context1", value2: "context2" };
      }
      render() {
        return <Parent />;
      }
    }
    
    class Parent extends React.Component {
      render() {
        return <Child />
      }
    }
    

    子组件里拿出来

    class Child extends React.Component {
      render() {
        console.log(this.context.value1);
      }
    }
    

    当然,react 对上面的流程进行了封装,提供了 React.createContext 的 api 和 Provider、Consumer 组件。

    const Context = React.createContext();
    
    class Child extends React.Component {
      render() {
        return (
          <Context.Consumer>
            {({ value1 }) => {
              console.log(value1);
            }}
          </Context.Consumer>
        );
      }
    }
    
    class Parent extends React.Component {
      render() {
        return <Child />
      }
    }
    
    class Ancestor extends React.Component {
      render() {
        return (
          <Context.Provider value={{
            value1: "context1"
          }}>
            <Parent />
          </Context.Provider>
        );
      }
    }
    

    这里也是 provider 的思想。

    Angular2 的 providers

    angular 最大的特点就是实现了 ioc,也就是在容器内的对象,可以声明依赖对象,然后用到的时候会自动注入。这个对象的创建方式也是 provider 的形式。

    我们知道,provider 并不关心具体对象是怎么创建的,可以动态切换多种创建策略,而 angular2 就提供了 4种策略: Class、Factory、Value、Exsiting

    直接值:

    @NgModule({
      providers: [
           { provide: 'ggg', useValue: 'guang' }
      ]
    })
    export class MainModule { }
    

    已有的:

    @NgModule({
      providers: [
          { provide: 'ggg', useExisting: Guang }
      ]
    })
    export class MainModule { }
    

    类:

    @Injectable()
    export class Guang {
       constructor(public name: string) {
       }
    }
    @NgModule({
      providers: [
           { provide: 'ggg', useClass: Guang}
      ]
    })
    export class MainModule { }
    

    工厂:

    function guangFactory() {
      return () => { name: 'guang' };
    }
    
    @NgModule({
      providers: [
           { provide: 'ggg', useFacotry: guangFactory }
      ]
    })
    export class MainModule { }
    

    可以看到,angular 提供的 provider 具体的创建策略有好多种,工厂只是其中一种方式,这是 provider 和工厂的区别。

    总结

    provider 是一种创建对象的模式,但是和工厂不同,它是有不同的创建策略的,算是一种复合模式,工厂只是其中一种策略,这种模式在 Angular 的 ioc 创建对象的时候、VSCode 插件注册各种处理函数的时候都有大量应用,还有 React 也基于 Provider 做 context 的传递。

    Provider 是各种框架中频繁出现的一个概念,掌握 provider 的思想,对于理解框架还有我们设计代码架构都会有帮助。希望本文能够帮大家理解 Provider。

    大家还有没有在别的地方见过 Provider 呢?可以留言交流哦~


    起源地下载网 » 前端代码经常见到的 Provider 究竟是什么

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元