在前面的学习当中,学会了如何用文本插值输出数据。但如果我们需要根据某些规则或逻辑输出数据呢?在这种情况下,我们可以通地Vue中的计算属性,根据某些规则或逻辑输出数据。这种方式也很方便,但除了这些方式之外,还可以嵌入JavaScript的逻辑函数。有的时候我们还会从远程服务获取数据,使用前面提到的方式也是可以。那么,今天 我们学习一个新方法,使用methods属性向Vue实例引入新属性。该属性应该包含一个对象,其中键(key)为函数的名称,值(value)为函数本身。
在介绍methods之前,咱们先简单的回忆一下。比如我们有下面这个示例,我们的data数据中,有两个属性:firstName和lastName。我们的目的是输出一个fullName。
let app = new Vue({el: '#app',data () {return {firstName: 'Airen',lastName: 'Liao'}}})比如我们要在页面中输出全名,我们有两种方式,一种是文本插值方式:
{{ firstName }} {{ lastName }}可以看到输出我们需要的fullName,也就是"Airen Liao":
除了文本插值的方式之外,我们还可以使用Vue中的computed属性,可以在computed中创建一个fullName方法。其中键名就是函数名,比如fullName,而键值是函数:
let app = new Vue({el: '#app',data () {return {firstName: 'Airen',lastName: 'Liao'}},computed: {fullName: function () {return this.firstName + ' ' + this.lastName}}})这个时候,我们在元素中插入fullName,如下:
{{ fullName }}最终输出的也是我们希望要的结果。
如果你从未接触Vue中的计算属性computed,建议你点击这里或这里进行了解。
除了上面两种方式,我们还可以添加一个方法,即函数,它也可以为我们做这个。
正如前面提到的,函数必须在Vue中的methods属性下添加,这个有点类似于Vue中的计算属性computed。在Vue中,把methods被命名为方法,它也是让我们调用在对象上下文中的函数,它可以操作对象中包含的数据。在我们这个示例,对象其实就是Vue实例。
let app = new Vue({el: '#app',data () {return {firstName: 'Airen',lastName: 'Liao'}},methods: {}})该对象中的键将是方法的名称。在本例中,fullName就是methods的方法名,其值就是一个函数:
let app = new Vue({el: '#app',data () {return {firstName: 'Airen',lastName: 'Liao'}},methods: {fullName: function () {}}})实际上,Vue中的方法可用做很多事情,但是现在我们这个示例中的方法只返回一个字符串值,它可以通过文本插值来输出。那么,我们如何访问该方法中的数据属性呢?Vue代理的数据和方法在此上下文中都可用,所以this.firstName就是访问了data中的firstName属性。注意这是必需的。有了这个,我们就可以很容易地连接第一个和最后一个名称并返回结果。
let app = new Vue({el: '#app',data () {return {firstName: 'Airen',lastName: 'Liao'}},methods: {fullName: function () {return this.firstName + ' ' + this.lastName}}})再次注意了,Vue中的data和methods都是上下文中的变量,所以我们可以通过this.firstName的方式访问data中的firstName属性。如果我们想要,我们可以通过使用相同的方法从fullName()方法中访问其他方法,只需要末尾插入括号,使其成为方法调用。
好了,现在我们已经实现了我们的方法,让我们看看在模板中怎么使用它。事实上也是你期望的那样简单,在方法后面紧跟着圆括号。
{{ fullName() }}事实证明,Vue的methods也可以访问数据对象的属性,也同样能渲染出所需要的字符。如果运行上面的代码,我们应该可以看到我的全名会页面上输出。如下所示:
这个看上去和computed类似。截张图看个对比:
这两种方式,只要我们data中的数据做了改变,输出也会做相应的变化。我们可以在控制台上做个测试:
使用Vue的methods时,在调用methods定义的方法时,一定得加上小括号(),不然输出的将是整个函数中的字符,类似下图这样:
在Vue中,使用methods可以做computed同样的事情,但两者之间还是有所差别的。让我们尝试一种稍微不同的方法。如果我们希望将第一个和最后一个名字传递给方法作为参数,而不是让方法直接访问数据属性,那该怎么办?我们可以很容易地在方法中添加参数,就像我们在JavaScript中的函数传参数那样。
我将对参数使用不同的名称,这样它们就不会和data对象的属性同名,造成一定的混淆,这样做只是为了证明我们不再依赖于数据中的属性。
let app = new Vue({el: '#app',data () {return {firstName: 'Airen',lastName: 'Liao'}},methods: {fullName: function (first, last) {return first + ' ' + last}}})然后,在模板中,我们只需要通过使用数据对象中的适当属性名作为fullName的参数传递进去,比如:
{{ fullName(firstName, lastName) }}这样也能得到我们想要的结果,在页面上输出我的全名。除此之外,我们还可以像JavaScript的函数调用一样,传一些不在data中的属性做为参数,也能输出到页面上,如:
{{ fullName('大漠', 'w3cplus.com') }}效果如下:
除了像上面一样,在方法中返回字符串之外,我们还可以返回对象和数组。比如我们重构上面的方法,让这个方法返回一个对象而不是字符串。比如下面的示例,咱们返回一个叫name的对象,而这个对象正如你所期望的一样,输出全名。
let app = new Vue({el: '#app',data () {return {firstName: 'Airen',lastName: 'Liao'}},methods: {fullName: function(first, last) {return {name: first + ' ' + last}}}})在模板中,我们仍然像以前一样调用方法。运行代码将打印出对象,这不是我们想要的。在方法调用之后,需要访问fullName对象的name名。再次运行代码将显示相同的结果。这也适用于嵌套对象。
在Vue中使用methods时有一个细节需要注意。如果你试图在方法对象中使用ES6箭头函数,那么你将无法访问其他方法或数据属性。这主要是因为箭头函数被绑定到父上下文(Parent Context),因此这个关键字不会像你期望那样引用Vue实例。因此,你试图以这种方式访问的任何数据属性或方法都将是未定义的。解决方法很简单:在方法对象中使用ES5语法的函数。
虽然 ES6的箭头函数非常有用,但在Vue的methods中使用,将会发生什么?我们简单的用示例来演示。将前面示例中的fullName函数改用箭头函数的写法:
methods: {fullName: () => {return this.firstName + ' ' + this.lastName}}运行上面的代码,在页面上并未能如你所期望的一样输出我的全名。这是因为箭头函数被绑定到父上下文,因此这将不是你所期望的Vue实例。当你打开浏览器的控制台时,可以看到有报错信息:
报错信息中告诉我们firstName是undefined。我们在代码中添加console.log(this)。正如我们所看到的,this指向的是window对象,这不是我们所期望的。这就是为什么在这种情况下,我们没有firstName或lastName属性。相比之下,我们使用正常函数,看看是什么样子:
现在,我们可以看到Vue实例的输出,就像我们最初期望的那样。
这个实例告诉我们不应该在Vue实例属性上使用箭头函数,Vue尝试将其绑定到Vue实例本身。还有时候,你可以使用箭头函数提供所有的好处,例如,如果你将一个函数赋给一个Vue实例的方法中的一个变量。然后你可以在这个箭头函数中访问它,它将指向你所期望的Vue实例。你只要意识到使用箭头函数的地方可能会出现一些奇怪的行为,而不是你所期望的,那么它可能与箭头函数有关。这时需要注意,先尝试把箭头函数改成ES5的函数方式。
Methods vs Computed前面的示例我们可以看到,methods和computed都可以处理大量的逻辑代码。有时候他们得到的效果是一样的。虽然如此,但他们各自却有不同之处。从作用机制和性质上看,methods和computed不太一样,所以我们接下来主要了解两者之间的对比。从两者对比来了解他们之间的不同之处。
从作用机制上看:
computed是以Vue的依赖追踪机制为基础的,其试图处理这样的一件事情:当某一个数据(依赖数据)发生变化的时候,所有依赖这个数据的相关数据会自动发生变化,也就是自动调用相关的函数去实现数据的变动methods里面是用来定义函数的,它需要手动调用才能执行,而不像computed那样,可以自动执行预先定义的函数methods里面定义的函数是需要主动调用的,而computed里定义的函数会自动调用,完成我们希望完成的作用
从性质上看:
computed是计算属性,事实上和data对象里的数据属性是同一类的methods里面定义的是函数,要像JavaScript中的function()函数这样去调用它例如:
computed: {fullName: function () {return this.firstName + ' ' + this.lastName}}你在取用的时候,用this.fullName去取用就和取data一样(不要当成函数调用)。
Vue中的computed擅长处理的场景是:一个数据受多个数据影响
比如我们有一个这样的场景,我本来想用“W3cplus_大漠(只会写CSS)”来描述自己,但希望能把“只会写CSS”改成“切图仔”,那么我们可以这样来写:
let app = new Vue({el: '#app',// data数据中:comeFrom, name,professional// computed监控数据:fullName// 两者关系: fullName = comeFrom + name + professional// 所以等式右边三个数据任一改变,都会直接修改fullNamedata () {return {comeFrom: 'W3cplus',name: '大漠',professional: '只会写CSS'}},computed: {fullName: function () {return this.comeFrom + '-' + this.name + '(' + this.professional + ')'}}}){{ fullName }}希望能把“只会写CSS”改成“切图仔”,尝试修改data中的professional的值为"切图仔",比如:
methods不处理数据逻辑关系,只提供可调用的函数。正如前面的示例所演示的一样。
在很多时候,computed是用来处理你使用methods的时候无法处理或者是处理起来并不太恰当的情况的。另外可以利用computed处理methods存在的重复计算情况,如下图所示:
methods里面的函数就是一群“直男”,如果有其他父函数调用它,它会每次都执行并返回结果,即使这些结果很可能是相同的,是不需要的;而computed是一个“心机婊”,它会以Vue提供的依赖追踪系统为基础,只要依赖数据没有发生变化,computed就不会再度进行计算。
比如下面这个时间的示例:
let app = new Vue({el: '#app',methods: {getMethodsDate: function () {console.log(new Date())},getComputedDate: function () {console.log(this.computedDate)}},computed: {computedDate: function () {return new Date()}}})Methods Get DateComputed Get Date先来看一个点击button在控制台的输出:
不难发现,连续点击两次methods返回的时间是不同的;连续点击两次computed返回的时间是相同的。
为什么两次点击computed返回的时间是相同的呢?new Date()不是依赖型数据(不是放在data等对象下的实例数据),所以computed只提供了缓存的值,而没有重新计算。
只有符合:存在依赖型数据和依赖型数据发生改变这两个条件,computed才会重新计算。 而methods下的数据,是每次都会进行计算的。使用官方的描述:
我们可以将同一函数定义为一个方法而不是一个计算属性。对于最终的结果,两种方式确实是相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
总结今天我们主要学习了Vue中的methods怎么使用。顺便介绍了methods和computed两者之间的异同。
由于作者自身是Vue的初学者,如果文中有不对之处,还请各路大婶拍正,如果在这方面有