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

更新日期: 2021-08-08 阅读: 1.7k 标签: 代码

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

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

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

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

  • provider 是什么
  • provider 创建对象和 factory 有什么区别
  • 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。

作者:zxg_神说要有光
链接:https://juejin.cn/post/6993837545461121038
来源:掘金

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/10619

相关推荐

减少嵌套,降低代码复杂度

减少嵌套会让代码可读性更好,同时也能更容易的找出bug,开发人员可以更快的迭代,程序也会越来越稳定。简化代码,让编程更轻松!

js高亮显示关键词_页面、搜索关键词高亮显示

页面实现关键词高亮显示:在项目期间遇到一个需求,就是搜索关键词时需要高亮显示,主要通过正则匹配来实现页面关键词高亮显示。在搜索结果中高亮显示关键词:有一组关键词数组,在数组中筛选出符合关键字的内容并将关键字高亮

Js代码压缩工具推荐

JavaScript 代码压缩是指去除源代码里的所有不必要的字符,而不改变其功能的过程。这些不必要的字符通常包括空格字符,换行字符,注释以及块分隔符等用来增加可读性的代码,但并不需要它来执行。

源代码是什么意思

源代码(也称源程序),是指一系列人类可读的计算机语言指令。 在现代程序语言中,源代码可以是以书籍或者磁带的形式出现,但最为常用的格式是文本文件,这种典型格式的目的是为了编译出计算机程序。

tinymce与prism代码高亮实现及汉化的配置

TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,由JavaScript写成。它对IE6+和Firefox1.5+都有着非常良好的支持。功能方强大,并且功能配置灵活简单。另一特点是加载速度非常快的。

Google内部在代码质量上的实践

良好的编程习惯涉及到很多方面,但在软件行业内,大多数的公司或组织都不会把良好的编程习惯列为主要关注点。 例如,具有可读性和可维护性的代码比编写好的测试代码或使用正确的工具更有意义,前者的意义在于可以让代码更易于理解和修改。

接手代码太烂,要不要辞职?

朋友发表了一条说说:入职新公司,从重构代码到放弃”,我就问他怎么了?他说,刚进一家新公司,接手代码太烂,领导让我先熟悉业务逻辑,然后去修复之前项目中遗留的bug,实在不行就重构

网站加入收藏、设为首页Js代码(兼容各种浏览器)

这里虽然说是兼容,但是有些浏览器的设置就是不支持用js来把页面设为首页,加入收藏夹,只能让用户手动去在浏览器或者按键去设置这些功能,这里说的兼容是指当浏览器有这个设置的时候js会有提示

提升JavaScript代码质量的最佳实践

在JavaScript编程中,代码质量优化是一项重要的技能。它可以帮助我们提高代码的可读性、可维护性和性能。本文将通过一些实际优化过程中的案例,展示如何通过一些技巧和最佳实践,使我们的代码更加优雅。

javascript代码语句结束要不要加分号?

在 C 语言中,分号是语句结束的标志,在语句结束的地方一定要以分号结束。而 JavaScript 的分号却是可选的,若语句都各占一行,则可以省略分号。avaScript 中的 ASI 机制,允许我们省略分号。ASI 机制不是说在解析过程中解析器自动把分号添加到代码中

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!