本人是Java背景,许多年前刚接触JavaScript时有点怪怪的,因为它没有 getters 和 setters。随着时间的推移,我开始喜欢上这个缺失的特性,因为相比Java大量的 getter 和 setter,它让代码更简洁。例如,我们看看下面的Java代码:
class Person{
String firstName;
String lastName;
// 这个Demo中省略了一些构造器代码 :)
public void setFirstName(firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
}
// Create instance
Person bradPitt = new Person();
bradPitt.setFirstName("Brad");
bradPitt.setLastName("Pitt");
JavaScript开发人员永远不会这样做,相反他们会这样:
var Person = function () {
};
var bradPitt = new Person();
bradPitt.firstName = 'Brad';
bradPitt.lastName = 'Pitt';
这要简洁的多。通常简洁更好,不是吗?
的确如此,但有时我想获取一些可以被修改的属性,但我不用知道这些属性是什么。例如,我们在Java代码中扩展一个新的方法 getFullName():
class Person{
private String firstName;
private String lastName;
// 这个Demo中省略了一些构造器代码 :)
public void setFirstName(firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
}
Person bradPitt = new Person();
bradPitt.setFirstName("Brad");
bradPitt.setLastName("Pitt");
// Prints 'Brad Pitt'
System.out.println(bradPitt.getFullName());
在上面例子中, fullName 是一个计算过的属性,它不是私有属性,但总能返回正确的结果。
我们来看看 C# 特性之一:隐式的 getters/setters,我真的很喜欢它。在 C# 中,如果需要,你可以定义 getters/setters,但是并不用这样做,但是如果你决定要这么做,调用者就不必调用函数。调用者只需要直接访问属性,getter/setter 会自动在钩子函数中运行:
public class Foo {
public string FirstName {get; set;}
public string LastName {get; set;}
public string FullName {get { return firstName + " " + lastName }; private set;}
}
我觉得这很酷...
现在,如果我想在JavaScript中实现类似的功能,我会浪费很多时间,比如:
var person0 = {
firstName: 'Bruce',
lastName: 'Willis',
fullName: 'Bruce Willis',
setFirstName: function (firstName) {
this.firstName = firstName;
this.fullName = `${this.firstName} ${this.lastName}`;
},
setLastname: function (lastName) {
this.lastName = lastName;
this.fullName = `${this.firstName} ${this.lastName}`;
},
};
console.log(person0.fullName);
person0.setFirstName('Peter');
console.log(person0.fullName);
它会打印出:
"Bruce Willis"
"Peter Willis"
但使用 setXXX(value) 的方式并不够'JavaScripty'(是个玩笑啦)。
下面的方式可以解决这个问题:
var person1 = {
firstName: 'Brad',
lastName: 'Pitt',
getFullName: function () {
return `${this.firstName} ${this.lastName}`;
},
};
console.log(person1.getFullName()); // 打印 "Brad Pitt"
现在我们回到被计算过的 getter。你可以设置 first 或 last name,并简单的合并它们的值:
person1.firstName = 'Peter'
person1.getFullName(); // 返回 "Peter Pitt"
这的确更方便,但我还是不喜欢它,因为我们要定义一个叫getxxx()的方法,这也不够'JavaScripty'。许多年来,我一直在思考如何更好的使用 JavaScript。
在我的Youtube频道,很多和Vue教程有关的视频都讲到,我习惯响应式开发,在更早的angular1时代,我们叫它:数据绑定(Data Binding)。它看起来很简单。你只需要在Vue实例的 data() 块中定义一些数据,并绑定到html:
var vm = new Vue({
data() {
return {
greeting: 'Hello world!',
};
}
})
<div>{greeting}</div>
显然它会在用户界面打印出 “Hello world!”。
现在,如果你改变greeting的值,Vue引擎会对此作出反应并相应地更新视图。
methods: {
onSomethingClicked() {
this.greeting = "What's up";
},
}
很长一段时间我都在想,它是如何工作的?当某个对象的属性发生变化时会触发某个事件?或者Vue不停的调用 setInterval 去检查是否更新?
通过阅读Vue官方文档,我才知道,改变一个对象属性将隐式调用getter/setter,再次通知观察者,然后触发重新渲染,如下图,这个例子来自官方的Vue.js文档:
但我还想知道:
第一个问题很简单:Vue为我们准备好了一切。当你添加新数据,Vue将会通过其属性为其添加 getter/setters。但是我让 foo.bar = 3? 会发生什么?
这个问题的答案出现在我和SVG & Vue专家Sarah Drasner的Twitter对话中:
Timo: foo.bar=value;是怎么做到实时响应的?
Sarah: 这个问题很难在Twitter说清楚,可以看这篇文章
Timo: 但这篇文章并没有解释上面提到的问题。
Timo: 它们就像:分配一个值->调用setter->通知观察者,不理解为什么在不使用setInterval和Event的情况下,setter/getter就存在了。
Sarah: 我的理解是:你获取的所有数据都在Vue实例data{}中被代理了。
显然,她也是参考的官方文档,之前我也读过,所以我开始阅读Vue源码,以便更好的理解发生了什么。过了一会我想起在官方文档看到一个叫 Object.defineProperty() 的方法,我找到它,如下:
/**
* 给对象定义响应的属性
*/
export function definereactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function,
shallow?: boolean
) {
const dep = new Dep()
const property = Object.getOwnPropertyDescriptor(obj, key)
if (property && property.configurable === false) {
return
}
// 预定义getter/setters
const getter = property && property.get
const setter = property && property.set
let childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
}
if (Array.isArray(value)) {
dependArray(value)
}
}
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
/* 禁用eslint 不进行自我比较 */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* 开启eslint 不进行自己比较 */
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
dep.notify()
}
})
}
所以答案一直存在于文档中:
把一个普通 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是仅 ES5 支持,且无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器的原因。
我只想简单的了解 Object.defineProperty() 做了什么,所以我用一个例子简单的给你讲解一下:
var person2 = {
firstName: 'George',
lastName: 'Clooney',
};
Object.defineProperty(person2, 'fullName', {
get: function () {
return `${this.firstName} ${this.lastName}`;
},
});
console.log(person2.fullName); // 打印 "George Clooney"
还记得文章开头C#的隐式 getter 吗?它们看起来很类似,但ES5才开始支持。你需要做的是使用 Object.defineProperty() 定义现有对象,以及何时获取这个属性,这个getter被称为响应式——这实际上就是Vue在你添加新数据时背后所做的事。
学完这一切,我一直在想,Object.defineProperty() 是否能让Vue变的更简化?现今越来越多的新术语,是不是真的有必要把事情变得过于复杂,变的让初学者难以理解(Redux也是同样):
你是怎么认为的?Vuex必须是复杂的还是可以像 Object.defineProperty() 一样简单?
特别声明,本文转载@余震翻译@Rockjins Blog的《Understanding Vue.js Reactivity in Depth with Object.defineProperty()》
英文地址:https://www.timo-ernst.net/blog/2017/07/26/understanding-vue-js-reactivity-depth-object-defineproperty
译文地址:https://juejin.im/post/59a7b01f6fb9a0249975d39f
VueJS 实际开发中会遇到的问题,主要写一些 官方手册 上没有写,但是实际开发中会遇到的问题,需要一定知识基础。
Vue.js是一套构建用户界面的渐进式的前端框架。 vueJS与后台交互数据的方法我所了解的有以下几种
Vue是一套构建用户界面的JS渐进式框架。 Vue 只关注视图层, 采用自底向上增量开发的设计。讲解js高级之响应式、过渡效果、过渡状态。
在vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示它的只属于当下的模块,这是一个非常好的举措,但是为什么要慎用呢?因为scoped往往会造成我们在修改公共组件(三方库或者项目定制的组件)的样式困难,需要增加额外的工作量
vue现在使用的人越来越多了,这篇文章主要整理一些比较优秀的移动端ui框架,推荐给大家,例如:mint UI、vux、vonic、vant、cube-ui、Muse-ui、Vue-Carbon、YDUI等
webpack是开发Vue单页应用必不可少的工具,它能管理复杂的构建步骤,并且优化你的应用大小和性能, 使你的开发工作流更加简单。在这篇文章中,我将解释使用webpack提升你的Vue应用的4种方式,包括:单文件组件、优化Vue构建过程、浏览器缓存管理、代码分离
Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。
Web 中的组件其实就是页面组成的一部分,具有高内聚性,低耦合度,互冲突等特点,有利于提高开发效率,方便重复使用,简化调试步骤等。vue 中的组件是一个自定义标签形式,扩展原生的html元素,封装可重用的代码。
Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理、数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成、编译、挂着、销毁等过程进行js控制。
主要讲Vue三种方式调用组件:v-model或者.sync显式控制组件显示隐藏,通过js代码调用,通过Vue指令调用,在写组件的时候很多写法、灵感来自于element-ui
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!