1. 想了解下依赖收集的过程?
答:
其实我写文的时候有考虑过介绍这个过程。不过当时考虑:
- 这个过程很细节
- 对实际开发帮助不大
- 有人写的比我更好
所以就没有具体展开讲。
依赖收集的过程请大家看这篇:https://ustbhuangyi.github.io/vue-analysis/reactive/getters.html#%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90。我希望跟大家分享一些实际生产中的收获。
如果大家看完还有别的问题,或者特别想听我讲,我再写,先下一个问题吧。(完)
2. Vue 事件机制与在 prop 中传入 function 有什么细微的区别吗?
(其实我比较喜欢这样的问题,哈哈)
众所周知,JS 里一切都是对象,function 也是个对象,所以 function 可以通过各种途径传递。那么,使用 prop
传递 function 自然是可行的。
传递过来的 function,它为作为当前实例的属性来使用,也就是 this.someFunction()
,那么自然而言,它也会遵守 JS 语法中的 this
指向,即“默认指向执行者”,也就是当前实例。所以它的用法跟当前类上声明的方法一致。
需要注意的是,如果我们使用 ES6+ 里新增的箭头函数,那么它会指向声明时的实例,未必是当前实例,这点需要注意。
Vue 的事件机制分两种,原生 DOM 事件,和人造事件,二者的差别主要在参数。Vue 在构建实例的时候,会把方法绑定到当前实例上,所以使用起来应该没什么不同。
比如 A 包括 B,B 在某些情况要调用 A 的某个方法。如果你在 B 里 a.foo()
,那么两个类就完全耦合了,必须同时存在。
(继续前面的)如果 A 接下来要 B 做一件事情,那么 A 应该再触发另一个事件,然后 B 来处理。这样,当你需要用 C 替换 A,或者 D 替换 B 的时候,就会非常容易。
(完)
3. Vue 有什么好的组件逻辑复用策略?
没记错的话,提问的同学还补充了一句:“mixin就算了”,所以我认为他的问题基本上可以理解成:如果像面向对象中的类的继承一样,复用 Vue 组件。
Vue 实际上提供了 2 种机制:
mixin
(实际也是一种很好的机制)- 组合式继承(好像是这样说法)
先说第一种,比如我们有一个类(组件)A,我现在需要给它增加一些功能,生成类 SubA,那么我们可以用 mixin
来实现:
import A from './A';
export default SubA {
mixins: [A],
// 继承的方法不用写
// 覆写的方法
methods: {
methodA(param1, param2) {
const result = A.methodA.call(this, param1, param2);
// 处理 result
return result;
},
},
};
只要注意钩子的使用,我认为用 mixin
实现继承也是个好方法。
还有一种,类似抽象类和具象类,比如下面这个截图,我需要对每种操作定义一个表单,所以我定义了一个抽象类 BaseForm:
- 它是一个组件
- 接受若干 slot,用来插入不同的表单项
- 包含一些基础的处理函数
- 其它类是“只有 BaeForm 组件”的组件
- 实现独立的表单处理,比如验证,数据加载
这种方法的写出的代码很清晰,很方便维护,但有一个问题,它增加了一层组件,使得组件之间传递数据有一些权衡,正如我文中写的那样。
mixin
钩子函数的执行顺序是死的:从前往后,从外往内。
如果有一个类,它的使命就是作为 mixin
让其它类继承,那么就尽量不要往他的钩子函数里写代码,而是写一个
methods: {
init() {
},
},
方便日后覆盖。
(完)
4. 对开源组件库有二次封装的方法论和最佳实践?
基本上,这个问题和上一个问题比较接近。二次封装应该解决两个需求:
- 给组件增加功能
- 组件的功能不合适我用,需要调整一下
那么做法无外乎:1. 使用 mixin
,使其作为我们代码的功能来源;2. 用它作为基类,我们自己写功能代码来实现自己的需要。
这里好像没有很多值得提的最佳实践。我能想到的就是把一些代码拿出来,独立封装成库,方便加入依赖管理。
5. 打包之后的代码如何知道跟原先代码的对应关系
首先,用 sourcemap。
其次,你要理解打包的本质。它并不是简单的替换,很多时候要做 AST 分析和重装,所以和原先的代码并不是绝对的一对一关系。好比英译中,很多时候可以翻译,有些时候不能翻译。
6. 能否对vuex有一个项目常用技能的大概解说
我文章中有一个章节就是讲 Vuex 和 Vue-Router 一起使用解决用户登录的,希望大家认真看下。
Vuex 其实没有很特别的用法,值得注意的是:
- 从设计思想上来说,它是把所有东西都装到自己的口袋里,然后谁用就找它要,这样可以避免一个数据传来传去,最后不知道在谁手里
- 用
mapState
实现getter
computed: {
...mapState('namespace', {
someFoo(state) {
return state.foo + 1;
},
someBar(state) {
return state.bar.charAt(0).toUpperCase();
},
}),
}
action
实际上会返回 Promise 实例,所以可以这样用:
this.$store.dispatch(GET_POST)
.then(posts => {
this.posts = posts;
});
这个写法在下面这种场景中非常有用:
- 想象一个博客网站,可以写博文,博文有分类和标签
- 分类和标签都可以自己编辑
- 发布博文的时候,可以选择分类和标签
那么,我比较喜欢这样做:
- 在标签列表,读取标签后,按照 key 把它们放到 vuex 里
- CRUD 标签后,更新 vuex 里的数据
- 需要选择标签时,直接从 vuex 里取
实际生产中效率很高,我甚至专门写了个类来负责这个业务。
7. vue 组件封装有什么经验?
实际上,MVVM 框架下,“组件化”的必要性并不大,至少与 jQuery 时代相比,我们并不怎么需要可以组件化。还有一个原因,HTML 和 CSS 不断吸收实践经验,很多东西都可以用原生来做,比如 <input type="date">
,还有普及中的 <dialog>
。
我觉得目前真正需要的组件有以下这些,这些组件没有原生方案,并且逻辑非常独特(几乎不会对业务逻辑产生干扰):
- modal
- typeahead
- dropdown
- tabs
其它基本上原生就够,或者很容易写出来。
所以我习惯先用 HTML 写,然后慢慢寻找需要组件化的“组件”,然后重构成组件,然后再反复用这些组件。其它大部分组件,在业务中很可能会成为桎梏。比如表单组件。很多表单组件可以从 schema 构建一个表单。当表单足够简单,或者是“用户生成”的时候,这个组件有一定价值。如果是比较复杂的表单要求,那就很影响开发效率。
所以我会在文中讨论“灵活与可靠”。
8. 讲讲前端职业发展方向,例如如何成为前端架构师等
首先,我不认为存在“前端架构师”,只有“系统架构师”。
其次,想成为“前端架构师”,你至少应该在一个万人规模以上的大型公司。
好,避除“前端架构师”这个概念以外,现在,前端职业发展方向还是很广的:
- 以 Vue、小程序通用解决方案为主的“语言”类(写一种语言,方便开发多平台)
- 数据可视化方向(数据处理、绘图)
- 以界面布局为主重构类(传统页面仔)
- 以业务为主的普通开发(vue 用户最多的地方)
- 页面自动化,尤其是自动化测试
- 比较复杂的交互,比如 Office、ProcessOn 等
- 业务中间层
- 多平台,尤其是移动平台
- 基础设施,比如组件库、工具链开发等
我认为每个方向都有很大的前景,很好的未来,选择合适自己的、合适公司的、合适行业的,就可以。大家注意积累以下知识体系:
- 三大基础知识体系:HTML、CSS、JS,一定要掌握好。
- 网络基础,Linux 编程
- 其它软件工程体系:测试、CI、版本管理。
- 产品体系:UI、交互、流程、项目管理等。
9. 不太懂作用域插槽在实际应用中的意义,不知道什么时候该用
我在文中举了个例子,正是我实际开发中遇到的。
简单来说,作用域插槽的意义,就是:
- 父组件 = 业务组件
- 子组件 = 组件库里定义的组件
- 父组件决定它的最终形态
- 子组件决定它的数据
继续用文中的例子,一个表格,它可能有这样的需求:
(编辑/删除)
也可能有这样的需求:
(启用/停用/锁定/编辑/删除)
这样的场景下,只有父组件,也就是当前的页面,知道表格里应该有什么按钮,每个按钮对应什么操作,每个操作对应的什么请求。但是父组件不知道子组件渲染到哪一行。
子组件,即表格组件,会负责整个表格的渲染,包括翻页、搜索、排序等逻辑,但它不知道最后一列怎么处理。
这个时候就要用“作用域插槽”,结合二者使用。
- 理解为啥html,css,js要这么设计API才算看过吗