加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.zhandada.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > Asp教程 > 正文

新手向:如何给大型前端开源项目贡献源码

发布时间:2022-10-30 14:00:50 所属栏目:Asp教程 来源:网络
导读: 参与开源项目对开发者个人的好处是显而易见的:进一步熟悉你所使用的库,和其他开发者进行交流,提高技术水平和社区影响力,发现新的工作机会等等。特别是对于没有工作经验的在校大学生来说

参与开源项目对开发者个人的好处是显而易见的:进一步熟悉你所使用的库,和其他开发者进行交流,提高技术水平和社区影响力,发现新的工作机会等等。特别是对于没有工作经验的在校大学生来说,参与开源项目是体现技术热情和积累经验的一个好方法,能在简历筛选和面试环节得到面试官的青睐。

这篇文章将会和大家分享如何参与大型前端开源项目的开发。你将会看到:开源的门槛其实并不高,只要有贡献代码的意愿并了解最基本的流程,任何人都可以给大型前端开源项目添砖加瓦。

为了方便你理解这篇文章的内容,我会以我之前给西湖区最大的 React 组件库 Ant Design 做的一个新功能为例来讲解。这个新功能使得用户能够通过唯一的 key 来修改消息框(Message)的内容。

绝大多数的前端开源项目都在 GitHub 上维护。开源项目的用户们会将他们找到的 bug 或是功能请求(feature request)提交到这些项目的 issues 列表当中,贡献代码的第一步就从这里开始,即:找到你感兴趣的 issue。

如果你还不了解 GitHub 及它的基本使用,可以参考这一篇知乎回答:如何使用 GitHub。

比如 Ant Design 的 issues 中,你可以看到许多 bug 反馈和功能请求。

asp开源论坛_开源asp_asp开源系统

如何找到适合自己的项目和 issue,哪些 issue 比较容易上手呢?

对于新手来说,最好找这样的一些项目:

issue 方面,建议寻找这样的 issue:

找到了想要解决的 issue 之后,在 issue 下面留言说你想要负责这个 issue,一般项目的维护者都会把这个 issue 交给你。你可以看到我在原 issue 下的回复。

维护者们都巴不得有人来完(tian)善(keng)他们的项目呢,所以尽管留言吧!

对于你的初体验,要记得 issue 的难度并不重要,重要的是走一遍贡献代码的流程,了解开源社区是如何协作的。

好了,现在我们手头已经有了一个待解决的 issue,接下来我们需要了解这个项目是如何运作的。

阅读源码的能力是必须的,这里推荐阅读《如何阅读大型前端开源项目的代码》。

了解项目的第一步永远都是先把这个项目在本地运行起来。

如果你在阅读下面的内容的时候发现对一些概念一无所知,请立刻回头阅读 如何使用 GitHub。

首先你要 fork 该项目,fork 意味者创建一份源仓库的拷贝,在贡献代码的时候,我们没有向源仓库推送(push)代码的权限,往往都需要先推送到自己的拷贝上,然后请求项目的维护者们合并我们的新代码,即发起 Pull Request。

你可以看到我的账户底下就有一份 ant-design 的 fork。

然后把 fork 后的代码 clone 到你的电脑。

asp开源论坛_开源asp_asp开源系统

通过 npm 或者 yarn 安装依赖。

一般通过查看 package.json 文件的 scripts 字段,就可以知道如何运行该项目,进行测试等等。对于 Ant Design,只需要运行 npm start 就可以。

asp开源论坛_asp开源系统_开源asp

下面我们就要解决 issue 中提出的功能请求了。

这一段会比较具体,对于其他开源项目不具有通用性,不感兴趣的话可以直接跳过。

我们先前提到 Notifcation 组件早已实现了此功能,先来看看它是如何实现的。

我们可以追溯到开源asp,当用户通过 Notification.open 方法创建一个 Notification 实例的时候,最终会调用到 getNotificationInstance 方法上(源码在此)。

getNotificationInstance(
    {
      prefixCls: outerPrefixCls,
      placement,
      top,
      bottom,
      getContainer,
    },
    (notification: any) => {
      notification.notice({
        content: (
          <div className={iconNode ? `${prefixCls}-with-icon` : ''}>
            {iconNode}
            <div className={`${prefixCls}-message`}>
              {autoMarginTag}
              {args.message}
            div>
            <div className={`${prefixCls}-description`}>{args.description}div>
            {args.btn ? <span className={`${prefixCls}-btn`}>{args.btn}span> : null}
          div>
        ),
        duration,
        closable: true,
        onClose: args.onClose,
        onClick: args.onClick,
        key: args.key,
        style: args.style || {},
        className: args.className,
      });
    },
  );
}

可以看到 key 是第二个回调参数的一部分。那么在 Message 组件中有没有类似的代码呢?可以发现的确存在这样的代码(链接在此)!

function notice(args: ArgsProps): MessageType {
  const duration = args.duration !== undefined ? args.duration : defaultDuration
  const iconType = {
    info: 'info-circle',
    success: 'check-circle',
    error: 'close-circle',
    warning: 'exclamation-circle',
    loading: 'loading',
  }[args.type]
  const target = key++
  const closePromise = new Promise(resolve => {
    const callback = () => {
      if (typeof args.onClose === 'function') {
        args.onClose()
      }
      return resolve(true)
    }
    getMessageInstance(instance => {
      const iconNode = (
        <Icon
          type={iconType}
          theme={iconType === 'loading' ? 'outlined' : 'filled'}
        />
      )
      const switchIconNode = iconType ? iconNode : ''
      instance.notice({
        key: target,
        duration,
        style: {},
        content: (
          <div
            className={`${prefixCls}-custom-content${
              args.type ? ` ${prefixCls}-${args.type}` : ''
            }`}
          >
            {args.icon ? args.icon : switchIconNode}
            <span>{args.content}span>
          div>
        ),
        onClose: callback,
      })
    })
  })
  const result: any = () => {
    if (messageInstance) {
      messageInstance.removeNotice(target)
    }
  }
  result.then = (filled: ThenableArgument, rejected: ThenableArgument) =>
    closePromise.then(filled, rejected)
  result.promise = closePromise
  return result
}

那我们是不是依样画葫芦,直接允许 key 使用用户传递进来的值呢?试了一下果然可以!

- key: target,
+ key: args.key || target,

这功能实现起来就非常简单。我们接着修改一下测试,添加一下 demo 即可。

以下是对该功能的测试代码(链接在此):

it('should support update message content with a unique key', () => {
  const key = 'updatable'
  class Test extends React.Component {
    componentDidMount() {
      message.loading({ content: 'Loading...', key })
      // Testing that content of the message should be updated.
      setTimeout(() => message.success({ content: 'Loaded', key }), 1000)
      setTimeout(() => message.destroy(), 3000)
    }
    render() {
      return <div>testdiv>
    }
  }
  mount(<Test />)
  expect(document.querySelectorAll('.ant-message-notice').length).toBe(1)
  jest.advanceTimersByTime(1500)
  expect(document.querySelectorAll('.ant-message-notice').length).toBe(1)
  jest.runAllTimers()
  expect(document.querySelectorAll('.ant-message-notice').length).toBe(0)
})

开源项目特别重视测试,还会有覆盖率检查工具来检查是否有代码未被测试覆盖,当你修复了一个 bug 或者新增了一个功能的时候,记得一定要写测试!

再改改文档,说明我们增加了这样的一个功能,就可以发起 PR 啦。

发起 PR(Pull Request)时,需要 commit 代码,然后 push 到你 fork 的仓库。

如果你同时给一个项目解决好几个 issue,你应该从 master 分支 checkout 出多个分支,然后分别在这些分支上解决 issue。更好的实践是永远 checkout 一个新分支来解决 issue,不要向 master 分支提交任何代码。

提交 PR 之前,你并不需要确定已经做到尽善尽美了,肯定有一些东西要和项目维护者们进行讨论。

之后在 GitHub 上发起 PR,当你在 fork 的仓库推送了分支时,GitHub 会很聪明地询问你是否要发起 PR,点击绿色的小按钮之后,填写 PR 模板即可发起 PR。

asp开源论坛_开源asp_asp开源系统

asp开源论坛_asp开源系统_开源asp

“烦人”的维护者们是不会轻易让你的代码进入他们的主分支的!你必须接受维护者们的代码 review,有时候他们会要求你做出一些修改。

比如 afc163 认为加入 key 后参数数量过多,要求实现以对象的形式传参。

当然他们也是为了保证代码的质量而非存心跟你过不去,而且和维护者们的互动有助于你写出更鲁棒的代码和更精炼的 API 哦。

这种 review 和修改和互动可能会有很多轮。如果维护者们对你的 PR 和修改没有做出回应,你可以主动 @ 他们。

当维护者们对所有事情都表示满意,approve 了你的 PR,你就可以坐等代码被合并到 master 并成为该项目的 contributor 啦。之后你参与该项目的讨论时就会有个 Contributor 小徽章时刻提醒那些小白你是多么的牛逼(逃

asp开源论坛_asp开源系统_开源asp

温馨建议

Happy coding :)

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!