Home  >  Article  >  Web Front-end  >  Detailed explanation of Vue.js responsiveness principle

Detailed explanation of Vue.js responsiveness principle

小云云
小云云Original
2018-02-10 13:59:391833browse
<span style="font-size: 14px;">class Person{<br/>    String firstName;<br/>    String lastName;    // 这个Demo中省略了一些构造器代码 :)    public void setFirstName(firstName) {        this.firstName = firstName;<br/>    }    public String getFirstName() {        return firstName;<br/>    }    public void setLastName(lastName) {        this.lastName = lastName;<br/>    }    public String getLastName() {        return lastName;<br/>    }<br/>}// Create instancePerson bradPitt = new Person();<br/>bradPitt.setFirstName("Brad");<br/>bradPitt.setLastName("Pitt");<br/></span>

JavaScript developers would never do this, instead they would do this:

<span style="font-size: 14px;">var Person = function () {};var bradPitt = new Person();<br/>bradPitt.firstName = &#39;Brad&#39;;<br/>bradPitt.lastName = &#39;Pitt&#39;;<br/></span>

Be concise many. Brevity is usually better, isn't it?

That's true, but sometimes I want to get some properties that can be modified, but I don't have to know what these properties are. For example, we extend a new method <span style="font-size: 14px;">getFullName()</span> in Java code:

<span style="font-size: 14px;">class Person{    private String firstName;    private String lastName;    // 这个Demo中省略了一些构造器代码 :)    public void setFirstName(firstName) {        this.firstName = firstName;<br/>    }    public String getFirstName() {        return firstName;<br/>    }    public void setLastName(lastName) {        this.lastName = lastName;<br/>    }    public String getLastName() {        return lastName;<br/>    }    public String getFullName() {        return firstName + " " + lastName;<br/>    }<br/>}<br/><br/>Person bradPitt = new Person();<br/>bradPitt.setFirstName("Brad");<br/>bradPitt.setLastName("Pitt");// Prints &#39;Brad Pitt&#39;System.out.println(bradPitt.getFullName());<br/></span>

In the above example , <span style="font-size: 14px;">fullName</span> is a calculated property, it is not a private property, but it always returns the correct result.

C# and implicit getters/setters

Let’s take a look at one of the C# features: implicit <span style="font-size: 14px;">getters</span>/<span style="font-size: 14px;">setters</span>, I really like it. In C#, if needed, you can define <span style="font-size: 14px;">getters</span>/<span style="font-size: 14px;">setters</span>, You don't have to do this, but if you decide to do it, the caller doesn't have to call the function. The caller only needs to access the property directly, and <span style="font-size: 14px;">getter</span>/<span style="font-size: 14px;">setter</span> will automatically Running in the hook function:

<span style="font-size: 14px;">public class Foo {    public string FirstName {get; set;}    public string LastName {get; set;}    public string FullName {get { return firstName + " " + lastName }; private set;}<br/>}<br/></span>

I think this is cool...

Now if I want to implement something like this in JavaScript , I will waste a lot of time, like:

<span style="font-size: 14px;">var person0 = {<br/>    firstName: &#39;Bruce&#39;,<br/>    lastName: &#39;Willis&#39;,<br/>    fullName: &#39;Bruce Willis&#39;,<br/>    setFirstName: function (firstName) {        this.firstName = firstName;        this.fullName = `${this.firstName} ${this.lastName}`;<br/>    },<br/>    setLastname: function (lastName) {        this.lastName = lastName;        this.fullName = `${this.firstName} ${this.lastName}`;<br/>    },<br/>};<br/>console.log(person0.fullName);<br/>person0.setFirstName(&#39;Peter&#39;);<br/>console.log(person0.fullName);<br/></span>

it will print out:

<span style="font-size: 14px;">"Bruce Willis"<br/>"Peter Willis"<br/></span>

but use ## The #setXXX(value)<span style="font-size: 14px;"></span> method is not 'JavaScripty' enough (it's a joke).

The following way can solve this problem:

<span style="font-size: 14px;">var person1 = {<br/>    firstName: &#39;Brad&#39;,<br/>    lastName: &#39;Pitt&#39;,<br/>    getFullName: function () {        return `${this.firstName} ${this.lastName}`;<br/>    },<br/>};<br/>console.log(person1.getFullName()); // 打印 "Brad Pitt"<br/></span>

Now we return to the calculated getter<span style="font-size: 14px;"></span>. You can set first<span style="font-size: 14px;"></span> or last name<span style="font-size: 14px;"></span> and simply merge them Value:

<span style="font-size: 14px;">person1.firstName = &#39;Peter&#39;person1.getFullName(); // 返回 "Peter Pitt"<br/></span>

This is indeed more convenient, but I still don't like it because we have to define a function called getxxx()<span style="font-size: 14px;"></span> method, which is not 'JavaScripty' enough either. For many years, I've been thinking about how to better use JavaScript.

Then Vue appeared

In my Youtube channel, many videos related to Vue tutorials are mentioned. I am used to responsive development. , in the earlier Angular1 era, we called it: Data Binding. It looks simple. You just need to define some data in the data()<span style="font-size: 14px;"></span> block of your Vue instance and bind it to HTML:

<span style="font-size: 14px;">var vm = new Vue({<br/>    data() {<br/>        return {<br/>        greeting: &#39;Hello world!&#39;,<br/>        };<br/>    }<br/>})<div>{greeting}</div><br/></span>

Obviously it will print out "Hello world!"<span style="font-size: 14px;"></span> in the user interface.

Now, if you change the value of greeting<span style="font-size: 14px;"></span>, the Vue engine will react to this and update accordingly view.

<span style="font-size: 14px;">methods: {<br/>    onSomethingClicked() {        this.greeting = "What&#39;s up";<br/>    },<br/>}<br/></span>

For a long time I was wondering, how does it work? An event is triggered when an object's properties change? Or does Vue keep calling setInterval<span style="font-size: 14px;"></span> to check whether it is updated?

After reading the official Vue documentation, I learned that changing an object property will implicitly call getter<span style="font-size: 14px;"></span>/ setter<span style="font-size: 14px;"></span>, notify the observer again, and then trigger re-rendering, as shown below. This example comes from the official Vue.js document:

Detailed explanation of Vue.js responsiveness principle

但我还想知道:

  • 怎么让数据自带<span style="font-size: 14px;">getter</span>/<span style="font-size: 14px;">setters</span>

  • 这些隐式调用内部是怎样的?

第一个问题很简单:Vue为我们准备好了一切。当你添加新数据,Vue将会通过其属性为其添加 <span style="font-size: 14px;">getter</span>/<span style="font-size: 14px;">setters</span>。但是我让 <span style="font-size: 14px;">foo.bar = 3</span>? 会发生什么?

这个问题的答案出现在我和SVG & Vue专家Sarah Drasner的Twitter对话中:

Detailed explanation of Vue.js responsiveness principle

Timo: <span style="font-size: 14px;">foo.bar=value;</span>是怎么做到实时响应的?

Sarah: 这个问题很难在Twitter说清楚,可以看这篇文章

Timo: 但这篇文章并没有解释上面提到的问题。

Timo: 它们就像:分配一个值->调用<span style="font-size: 14px;">setter</span>->通知观察者,不理解为什么在不使用<span style="font-size: 14px;">setInterval</span><span style="font-size: 14px;">Event</span>的情况下,<span style="font-size: 14px;">setter</span>/<span style="font-size: 14px;">getter</span>就存在了。

Sarah: 我的理解是:你获取的所有数据都在Vue实例<span style="font-size: 14px;">data{}</span>中被代理了。

显然,她也是参考的官方文档,之前我也读过,所以我开始阅读Vue源码,以便更好的理解发生了什么。过了一会我想起在官方文档看到一个叫 <span style="font-size: 14px;">Object.defineProperty()</span> 的方法,我找到它,如下:

<span style="font-size: 14px;">/**<br/>* 给对象定义响应的属性<br/>*/export function defineReactive (<br/>    obj: Object,<br/>    key: string,<br/>    val: any,<br/>    customSetter?: ?Function,<br/>    shallow?: boolean<br/>) {    const dep = new Dep()    const property = Object.getOwnPropertyDescriptor(obj, key)    if (property && property.configurable === false) {        return<br/>    }    // 预定义getter/setters    const getter = property && property.get    const setter = property && property.set    let childOb = !shallow && observe(val)<br/>    Object.defineProperty(obj, key, {<br/>        enumerable: true,<br/>        configurable: true,        get: function reactiveGetter () {            const value = getter ? getter.call(obj) : val            if (Dep.target) {<br/>                dep.depend()                if (childOb) {<br/>                    childOb.dep.depend()<br/>                }                if (Array.isArray(value)) {<br/>                    dependArray(value)<br/>                }<br/>            }            return value<br/>        },        set: function reactiveSetter (newVal) {            const value = getter ? getter.call(obj) : val            /* 禁用eslint 不进行自我比较 */            if (newVal === value || (newVal !== newVal && value !== value)) {                return<br/>            }            /* 开启eslint 不进行自己比较 */            if (process.env.NODE_ENV !== &#39;production&#39; && customSetter) {<br/>                customSetter()<br/>            }            if (setter) {<br/>                setter.call(obj, newVal)<br/>            } else {<br/>                val = newVal<br/>            }<br/>            childOb = !shallow && observe(newVal)<br/>            dep.notify()<br/>        }<br/>    })<br/>}<br/></span>

所以答案一直存在于文档中:

把一个普通 JavaScript 对象传给 Vue 实例的 <span style="font-size: 14px;">data</span> 选项,Vue 将遍历此对象所有的属性,并使用 <span style="font-size: 14px;">Object.defineProperty</span> 把这些属性全部转为 <span style="font-size: 14px;">getter</span>/<span style="font-size: 14px;">setter</span><span style="font-size: 14px;">Object.defineProperty</span> 是仅 ES5 支持,且无法 <span style="font-size: 14px;">shim</span> 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器的原因。

我只想简单的了解 <span style="font-size: 14px;">Object.defineProperty()</span> 做了什么,所以我用一个例子简单的给你讲解一下:

<span style="font-size: 14px;">var person2 = {<br/>    firstName: &#39;George&#39;,<br/>    lastName: &#39;Clooney&#39;,<br/>};<br/>Object.defineProperty(person2, &#39;fullName&#39;, {<br/>    get: function () {        return `${this.firstName} ${this.lastName}`;<br/>    },<br/>});<br/>console.log(person2.fullName); // 打印 "George Clooney"<br/></span>

还记得文章开头C#的隐式 <span style="font-size: 14px;">getter</span> 吗?它们看起来很类似,但ES5才开始支持。你需要做的是使用 <span style="font-size: 14px;">Object.defineProperty()</span> 定义现有对象,以及何时获取这个属性,这个<span style="font-size: 14px;">getter</span>被称为响应式——这实际上就是Vue在你添加新数据时背后所做的事。

<span style="font-size: 14px;">Object.defineProperty()</span>Can Vue become simpler?

After learning all this, I have been thinking, <span style="font-size: 14px;">Object.defineProperty()</span> Can I make Vue change More simplified? Nowadays, there are more and more new terms. Is it really necessary to make things too complicated and difficult for beginners to understand (the same is true for Redux):

  • <span style="font-size: 14px;">Mutator</span>: Maybe you are saying (implicitly) <span style="font-size: 14px;">setter</span>

  • <span style="font-size: 14px;">Getters</span>: Why not replace <span style="font-size: 14px;">Object.defineProperty()</span> with (implicit )<span style="font-size: 14px;">getter</span>

  • ##store.commit()<span style="font-size: 14px;"></span>: Why not simplify it to foo = bar<span style="font-size: 14px;"></span>, but instead store.commit("setFoo", bar);<span style="font-size: 14px;"></span>?

#What do you think? Does Vuex have to be complex or can it be as simple as Object.defineProperty()<span style="font-size: 14px;"></span>?

Related recommendations:

javascript uses rem for responsive development Example sharing

Detailed explanation of front-end responsive layout, responsive images, and self-made grid system

What is the difference between responsive and adaptive

The above is the detailed content of Detailed explanation of Vue.js responsiveness principle. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn