宅码,构建相同的组件Vue3 vs Vue2

417 阅读7分钟
原文链接: zhaima.tech

构建相同的组件Vue3 vs Vue2

发布于3/4/2020 来自:「前端知否」微信公众号

随着Vue3即将发布,许多人都在想”Vue2与Vue3有何不同?”

尽管我们之前已经写过有关重大变化的文章,但实际上并没有真正深入地了解我们的代码将如何变化。因此,为了显示这些更改,我们将在Vue2和Vue3中构建一个简单的表单组件。

在本文中,您将了解Vue2和Vue3之间的主要编程差异,并逐步成为一名更好的开发人员。

如果您想知道如何构建第一个Vue3应用程序,请查阅Vue3 Composition API教程及示例

让我们开始吧!

创建模板

对于大多数组件,Vue2和Vue3中的代码将非常相似。但是,Vue3支持Fragments,这意味着组件可以具有多个根节点。

在渲染列表中的组件时,可以减少不必要的包装div元素,这特别有用。在这种情况下,我们将为两个版本的Form组件保留一个根节点。

<template>
  <div class='form-element'>
    <h2> {{ title }} </h2>
    <input type='text' v-model='username' placeholder='Username' />

    <input type='password' v-model='password' placeholder='Password' />

    <button @click='login'>
      Submit
    </button>
    <p> 
      Values: {{ username + ' ' + password }}
    </p>
  </div>
</template>

唯一真正的区别是我们访问数据的方式。在Vue3中,我们的响应式数据都包装在一个响应​​式状态变量中,因此我们需要访问该状态变量以获取我们的值。

<template>
  <div class='form-element'>
    <h2> {{ state.title }} </h2>
    <input type='text' v-model='state.username' placeholder='Username' />

    <input type='password' v-model='state.password' placeholder='Password' />

    <button @click='login'>
      Submit
    </button>
    <p> 
      Values: {{ state.username + ' ' + state.password }}
    </p>
  </div>
</template>

设置数据

这是一个重大的区别:Vue2 Options API与Vue3 Composition API。

Options API将我们的代码分为不同的属性:数据,计算属性,方法等。但是,Composition API允许我们按功能而不是属性的类型对代码进行分组

假设对于表单组件,我们只有两个数据属性:用户名和密码。

Vue2代码:

export default {
  props: {
    title: String
  },

  data() {
    return {
      username: '',
      password: ''
    }
  }
}

在Vue 3.0中,我们必须通过使用新的setup()方法进行更多的工作,在该方法中应进行所有组件初始化。

另外,为了使开发人员能够更好地控制数据响应,我们可以直接访问Vue的 reactive API。

创建响应性数据包含三个步骤:

  • 从Vue导入reactive
  • 使用reactive方法声明我们的数据
  • 让我们的设置方法返回响应性数据,以便我们的模板可以访问它

代码如下:

import { reactive } from 'vue'

export default {
  props: {
    title: String
  },

  setup() {
    const state = reactive({
      username: '',
      password: ''
    })

    return { state }
  }
}

然后,在模板中,我们可以使用state.username和state.password访问它们

在Vue2与Vue3中创建方法

Vue2 Options API有一个单独的方法部分。在其中,我们可以定义所有方法并以所需的任何方式组织它们。

export default {
  props: {
    title: String
  },

  data() {
    return {
      username: '',
      password: ''
    }
  },

  methods: {
    login() {
      // login method
    }
  }
}

Vue3 Composition API中的setup方法也可以处理方法。它的工作方式与声明数据有些类似。我们必须先声明我们的方法,然后返回它,以便组件的其他部分可以访问它。

export default {
  props: {
    title: String
  },

  setup() {
    const state = reactive({
      username: '',
      password: ''
    })

    const login = () => {
      // login method
    }

    return { 
      login,
      state
    }
  }
}

生命周期钩子

在Vue2中,我们可以直接在组件选项中设置生命周期钩子。

export default {
  props: {
    title: String
  },

  data() {
    return {
      username: '',
      password: ''
    }
  },

  mounted() {
    console.log('component mounted')
  },

  methods: {
    login() {
      // login method
    }
  }
}

现在有了Vue3 Composition API,几乎所有内容都在setup()方法内部。这包括mounted生命周期钩子。

但是,默认情况下不包括生命周期钩子,我们必须导入onMounted方法,作为Vue3中调用的方法。这与之前导入reactive相同。

然后,在setup方法中,可以通过给onMounted方法传递函数参数来使用它。

import { reactive, onMounted } from 'vue'

export default {
  props: {
    title: String
  },

  setup() {
    // ..

    onMounted(() => {
      console.log('component mounted')
    })

    // ...
  }
}

计算属性

让我们添加一个计算属性,将我们的用户名转换为小写字母。

为了在Vue2中完成此操作,我们需要添加computed字段到我们的options对象中。我们可以像这样定义我们的属性:

export default {
  // .. 
  computed: {
    lowerCaseUsername () {
      return this.username.toLowerCase()
    }
  }
}

Vue3的设计允许开发人员导入他们使用的内容。本质上,他们不希望开发人员必须包含从未使用过的东西,这在Vue2中正成为一个日益严重的问题。

因此,要在Vue3中使用计算属性,我们首先必须将computed导入到组件中。

然后,类似于我们之前创建响应式数据的方式,我们可以使一条响应式数据成为这样的计算值:

import { reactive, onMounted, computed } from 'vue'

export default {
  props: {
    title: String
  },

  setup() {
    const state = reactive({
      username: '',
      password: '',
      lowerCaseUsername: computed(() => state.username.toLowerCase())
    })

    // ...
  }
}

访问Props

访问Props带来了Vue2和Vue3之间的重要区别。

在Vue2中,我们可以轻松访问P。让我们添加一个简单的示例,例如在加载完成钩子上打印出标题prop:

mounted() {
  console.log('title: ' + this.title)
}

但是在Vue3中,我们不再使用this来访问Props,发出事件和获取属性。相反,setup()方法采用两个参数:

  • props -对组件的props的不变访问
  • context -Vue3公开的选定属性(emit,slot,attrs

使用props参数,上面的代码将如下所示:

setup(props) {
  // ...

  onMounted(() => {
    console.log('title: ' + props.title)
  })

  // ...
}

发出事件

同样,在Vue2中发出事件非常简单,但是Vue3使您可以更好地控制如何访问属性/方法。

假设在我们的情况下,我们想在按下“提交”按钮时向父组件发出一个登录事件。

Vue2代码只需要调用this.$ emit并传入我们的payload对象即可。

login() {
  this.$emit('login', {
    username: this.username,
    password: this.password
  })
}

但是,在Vue3中,我们现在知道这不再意味着同一件事,因此我们必须做不同的事情。

幸运的是,上下文对象公开了emit方法。

我们要做的就是将context添加为setup()方法的第二个参数。我们将解构上下文对象,以使我们的代码更简洁。

然后,我们只需要调用emit发送事件即可。像以前一样,emit方法采用两个参数:

  • 事件名称
  • 与事件一起传递的payload对象
setup(props, { emit }) {
  // ...

  const login = () => {
    emit('login', {
      username: state.username,
      password: state.password
    })
  }

  // ...
}

最终的Vue2与Vue3代码

我们已经完成了。如您所见,Vue2和Vue3中的所有概念都是相同的,但是我们访问属性的某些方式已经有所改变。

总的来说,我认为Vue3将帮助开发人员编写更有组织的代码,尤其是在大型项目中。这主要是因为Composition API允许我们按照特定功能将代码组织在一起,甚至可以将功能提取到单独文件中,然后根据需要将其导入组件中。

在Vue2中用于表单组件的代码:

<template>
  <div class='form-element'>
    <h2> {{ title }} </h2>
    <input type='text' v-model='username' placeholder='Username' />

    <input type='password' v-model='password' placeholder='Password' />

    <button @click='login'>
      Submit
    </button>
    <p> 
      Values: {{ username + ' ' + password }}
    </p>
  </div>
</template>

<script>
export default {
  props: {
    title: String
  },

  data() {
    return {
      username: '',
      password: ''
    }
  },

  mounted() {
    console.log('title: ' + this.title)
  },


  computed: {
    lowerCaseUsername () {
      return this.username.toLowerCase()
    }
  },

  methods: {
    login() {
      this.$emit('login', {
        username: this.username,
        password: this.password
      })
    }
  }
}
</script>

在Vue3中:

<template>
  <div class='form-element'>
    <h2> {{ state.title }} </h2>
    <input type='text' v-model='state.username' placeholder='Username' />

    <input type='password' v-model='state.password' placeholder='Password' />

    <button @click='login'>
      Submit
    </button>
    <p> 
      Values: {{ state.username + ' ' + state.password }}
    </p>
  </div>
</template>

<script>
import { reactive, onMounted, computed } from 'vue'

export default {
  props: {
    title: String
  },

  setup(props, { emit }) {
    const state = reactive({
      username: '',
      password: '',
      lowerCaseUsername: computed(() => state.username.toLowerCase())
    })

    onMounted(() => {
      console.log('title: ' + props.title)
    })

    const login = () => {
      emit('login', {
        username: state.username,
        password: state.password
      })
    }

    return { 
      login,
      state
    }
  }
}
</script>

最后

希望本教程有助于重点介绍Vue代码在Vue3中不同表现形式。编码愉快!