Pull Request 介绍 
贡献者请项目维护者“拉取”修改的软件内容(因此称为拉取请求),若此修改内容应该成为正式代码库的一部分,就需要合并拉取请求中提到的软件内容。 
最常用的方式是“Fork + Pull”模式:如果要为拉取请求创建新分支,又没有仓库的写入权限,可以先对仓库 Fork,仓库参与者不必向仓库创建者申请提交权限,而是在自己的托管空间下建立仓库的派生(Fork)。 
拉取请求只能在不同的两个分支之间打开,可以在创建拉取请求时指定要将更改合并到哪个分支。 
 
创建拉取请求 
Fork 创建存储库分支。 
进行修复。 
创建拉取请求。 
 
在存储库的主页“Branch(分支)”菜单中,选择包含提交的分支。 
 
使用基础分支下拉菜单选择要向其合并更改的分支,然后使用比较分支下拉菜单选择进行了更改的主题分支。 
 
要创建可供审查的拉取请求,请单击“创建拉取请求”。若要创建草稿拉取请求,请使用下拉列表并选择“创建草稿拉取请求”,然后单击“草稿拉取请求”。 
 
在拉取请求列表中,单击你想要请求特定人员或团队审查的拉取请求。 
导航到右侧边栏中的“审查者”。 
若要向建议的人员请求审查,请在“审查者”下其用户名旁,单击“请求” 。 
 
(可选)若要向建议人员以外的其他人请求审查,请单击“审查者”,然后单击下拉菜单中的姓名。 
 
更改后,可以请求审查者重新审查你的拉取请求。导航到右侧边栏中的“审查者”,然后单击你想要其审查的审查者姓名旁边的 
被请求的审查者或团队将收到你请求他们审查拉取请求的通知。如果你请求团队审查,并启用了代码评审分配,则会向特定成员发出请求,并且取消团队作为审查者。 
审查拉取请求后,对仓库具有推送权限的任何人都可以完成合并。 
 
合并拉取请求 
在存储库名称下,单击 “Pull requests”。 
 
在“Pull Requests(拉取请求)”列表中,单击要合并的拉取请求。 
根据对仓库启用的合并选项,你可以: 
 
单击“合并拉取请求”,将所有提交合并到基分支中。 如果未显示“合并拉取请求”选项,则单击合并下拉菜单,然后选择“创建合并提交” 。 
 
单击合并下拉菜单,选择“压缩并合并”,然后单击“压缩并合并”按钮,将多个提交压缩为一个提交。 
 
单击合并下拉菜单,选择“变基并合并”,然后单击“变基并合并”按钮,将多个提交变基为一个基分支。 
 
如有提示,输入提交消息,或接受默认消息。 
 
单击“确认合并”、“确认压缩并合并”,或“确认变基并合并” 。 
(可选)删除分支。这有助于仓库的分支列表保持整洁。 
 
给 layui- vue 提了个 PR,已合并 青训营中我们团队做的是组件库项目。因为我负责的是 Pagination 和 Table 组件,但 Ant Design Vue 和 Element Plus 的表格组件都太复杂了,所以我参考的是较简单的 layui - vue。
Bug 由于开发测试完组件后,也需要写对应的组件演示文档。在写文档过程中,发现了 Table 组件演示文档中的一个 Bug:
可以看到,行内编辑图标首次点击无效,只能从上到下开启编辑、从下到上关闭编辑,点击其他行图标也只从首行开始编辑。出问题的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 <template >   <lay-table  :columns ="columns28"  :data-source ="dataSource28" >      <template  #username ="{ data }" >        <lay-input  v-if ="edingKeys[data.id]"  :model-value ="data.username"  @input ="changeUsername($event, data)" >          <template  #suffix >            <lay-icon  type ="layui-icon-close"  style ="right:10px;"  v-if ="edingKeys[data.id]"  @click ="deleteEdit(data.id)" > </lay-icon >          </template >        </lay-input >        <span  v-else >          {{ data.username }}          <lay-icon  type ="layui-icon-edit"  style ="position: absolute;right: 10px;"  v-if ="!edingKeys[data.id]"  @click ="editHandle(data.id)" > </lay-icon >        </span >      </template >    </lay-table >  </template > <script > import  { ref } from  'vue' export  default  {  setup (     const  edingKeys = ref ([])     const  columns28 = [       {         title :"账户" ,         width :"200px" ,         key :"username" ,         customSlot : "username"        },{         title :"密码" ,         width : "300px" ,         key :"password"        },{         title :"性别" ,         key :"sex"        },{         title :"年龄" ,         width : "300px" ,         key :"age"        },{         title :"备注" ,         width : "180px" ,         key :"remark" ,         ellipsisTooltip : true        }     ]     const  dataSource28 = ref ([       {id :"1" ,username :"root" , password :"root" ,sex :"男" , age :"18" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"2" ,username :"root" , password :"root" ,sex :"男" , age :"18" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"3" ,username :"woow" , password :"woow" ,sex :"男" , age :"20" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"4" ,username :"woow" , password :"woow" ,sex :"男" , age :"20" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"5" ,username :"woow" , password :"woow" ,sex :"男" , age :"20" , remark : 'layui - vue(谐音:类 UI) ' }     ])     const  editHandle  = (key ) => {       edingKeys.value .push (key);     }     const  deleteEdit  = (key ) => {       edingKeys.value .splice (edingKeys.value .indexOf (key),1 );     }     const  changeUsername  = (val, data ) => {       dataSource28.value .forEach (element  =>         if (element.id  == data.id ) {           element.username  = val;         }       });     }     return  {       edingKeys,       deleteEdit,       columns28,       editHandle,       dataSource28,       changeUsername,     }   } } </script > 
上面代码在 lay-input、lay-icon type="layui-icon-close"、lay-icon type="layui-icon-edit" 这三个组件上使用 v-if 表达式来条件性地渲染元素时,条件分别为 edingKeys[data.id]、edingKeys[data.id] 和 !edingKeys[data.id]。响应式变量 edingKeys 初始化时是一个空数组,在点击行编辑图标时,由绑定的 editHandle 方法将当前行的 id 字段添加到数组中,然后由响应式对象 edingKeys 根据行的 id 字段动态改变上述三个条件表达式的值,从而动态渲染行的编辑状态。
问题出在:id 字段是数字类型字符串,而 在 JavaScript 中,可以同时使用字符串 arr["1"] 或数字 arr[1] 访问对象属性和数组元素。 
例如,当点击第三行的编辑图标时,editHandle 方法会将 "3" 添加到数组中,此时 edingKeys 的值为 ["3"],数组中只有一个元素,所以只有 edingKeys[0] 的条件为真,而 edingKeys[1]、edingKeys[2] 以后的值都为 undefined,条件都为假,所以第一次点击任何行时都不会有反应。然后我们点击第四行的编辑图标,此时 editHandle 方法会将 "4" 添加到数组中,此时 edingKeys 的值为 ["3", "4"],只有 edingKeys[0]、edingKeys[1] 的条件为真,而 edingKeys[2]、edingKeys[3] 以后的值都为 undefined,条件都为假。所以第一行变成了编辑状态,而不是第三行或第四行。
以此类推,继续点击将依次从从上到下开启编辑状态。当点击任意某个已经开启编辑状态的行上的关闭图标时,deleteEdit 方法会将当前行的 id 字段从 edingKeys 数组中删除,edingKeys 数组的长度将减一。所以会从 edingKeys 数组的长度减一索引处,即从 edingKeys[edingKeys.length-1] 开始取消编辑。继续点击任意关闭图标,将依次从下到上关闭行编辑状态。
解决方法 很简单,只需要把三个 v-if 表达式的条件 edingKeys[data.id]、edingKeys[data.id] 和 !edingKeys[data.id] 改为 edingKeys.includes(data.id)、edingKeys.includes(data.id) 和 !edingKeys.includes(data.id),includes() 方法用来判断一个数组是否包含一个指定的值。
但更完善的方法是在 editHandle 方法中将整个行数据而不是行的 id 字段添加到数组中,然后使用 edingKeys.includes(data)、edingKeys.includes(data) 和 !edingKeys.includes(data) 来判断编辑状态。因为行的 id 字段如果不是唯一的,即多行的 id 字段值相同,会出现点击一行的编辑和关闭图标,将同时开启和关闭多行的编辑状态。每行的行数据却是唯一的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 <template >   <lay-table  :columns ="columns28"  :data-source ="dataSource28" >      <template  #username ="{ data }" >        <lay-input  v-if ="edingKeys.includes(data)"  :model-value ="data.username"  @input ="changeUsername($event, data)" >          <template  #suffix >            <lay-icon  type ="layui-icon-close"  style ="right:10px;"  v-if ="edingKeys.includes(data)"   @click ="deleteEdit(data)" > </lay-icon >          </template >        </lay-input >        <span  v-else >          {{ data.username }}          <lay-icon  type ="layui-icon-edit"  style ="position: absolute;right: 10px;"  v-if ="!edingKeys.includes(data)"   @click ="editHandle(data)" > </lay-icon >        </span >      </template >    </lay-table >  </template > <script > import  { ref } from  'vue' export  default  {  setup (     const  edingKeys = ref ([])     const  columns28 = [       {         title :"账户" ,         width :"200px" ,         key :"username" ,         customSlot : "username"        },{         title :"密码" ,         width : "300px" ,         key :"password"        },{         title :"性别" ,         key :"sex"        },{         title :"年龄" ,         width : "300px" ,         key :"age"        },{         title :"备注" ,         width : "180px" ,         key :"remark" ,         ellipsisTooltip : true        }     ]     const  dataSource28 = ref ([       {id :"1" ,username :"root" , password :"root" ,sex :"男" , age :"18" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"2" ,username :"root" , password :"root" ,sex :"男" , age :"18" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"3" ,username :"woow" , password :"woow" ,sex :"男" , age :"20" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"4" ,username :"woow" , password :"woow" ,sex :"男" , age :"20" , remark : 'layui - vue(谐音:类 UI) ' },       {id :"5" ,username :"woow" , password :"woow" ,sex :"男" , age :"20" , remark : 'layui - vue(谐音:类 UI) ' }     ])     const  editHandle  = (data ) => {       edingKeys.value .push (data);     }     const  deleteEdit  = (data ) => {       edingKeys.value .splice (edingKeys.value .indexOf (data),1 );     }     const  changeUsername  = (val, data ) => {       dataSource28.value .forEach (element  =>         if (element.id  == data.id ) {           element.username  = val;         }       });     }     return  {       edingKeys,       deleteEdit,       columns28,       editHandle,       dataSource28,       changeUsername,     }   } } </script > 
修复后的效果:
提了 PR 由于 layui  仓库在 gitee,GitHub 上面的仓库已经撤下了,所以在 gitee 上面提的 PR,gitee PR 操作比 GitHub 更加方便和简单,在 Fork 项目的主页点击 + Pull Request 按钮,然后选择分支,输入标题和说明即可。
目前 已合并 。