飞道的博客

8 个很棒的 Vue 开发技巧

340人阅读  评论(0)

1.路由参数解耦

通常在组件中使用路由参数,大多数人会做以下事情。


   
  1. export default {
  2. methods: {
  3. getParamsId() {
  4. return this.$route.params.id
  5. }
  6. }
  7. }

在组件中使用 $route 会导致与其相应路由的高度耦合,通过将其限制为某些 URL 来限制组件的灵活性。正确的做法是通过 props 来解耦。


   
  1. const router = new VueRouter({
  2. routes: [{
  3. path: /user/:id ,
  4. component: User,
  5. props: true
  6. }]
  7. })

将路由的 props 属性设置为 true 后,组件内部可以通过 props 接收 params 参数。


   
  1. export default {
  2. props: [ id ],
  3. methods: {
  4. getParamsId() {
  5. return this.id
  6. }
  7. }
  8. }

您还可以通过功能模式返回道具。


   
  1. const router = new VueRouter({
  2. routes: [{
  3. path: /user/:id ,
  4. component: User,
  5. props: (route) => ({
  6. id: route.query.id
  7. })
  8. }]
  9. })

2.功能组件

功能组件是无状态的,它不能被实例化,也没有任何生命周期或方法。创建功能组件也很简单,只需在模板中添加功能声明即可。它一般适用于只依赖于外部数据变化的组件,并且由于其轻量级而提高了渲染性能。组件需要的一切都通过上下文参数传递。它是一个上下文对象,具体属性见文档。这里的 props 是一个包含所有绑定属性的对象。


   
  1. <template functional>
  2. <div class="list">
  3. <div class="item" v-for="item in props.list" :key="item.id" @click="props.itemClick(item)">
  4. <p>{ {item.title}}</p>
  5. <p>{ {item.content}}</p>
  6. </div>
  7. </div>
  8. </template>

父组件使用


   
  1. <template>
  2. <div>
  3. <List :list="list" :itemClick="item => (currentItem = item)" />
  4. </div>
  5. </template>

   
  1. import List from @/components/List.vue
  2. export default {
  3. components: {
  4. List
  5. },
  6. data() {
  7. return {
  8. list: [{
  9. title: title ,
  10. content: content
  11. }],
  12. currentItem:
  13. }
  14. }
  15. }

3.样式范围

开发中修改第三方组件样式很常见,但是由于scoped属性的样式隔离,可能需要去掉scoped或者另起一个样式。这些做法有副作用(组件样式污染,缺乏优雅),在css预处理器中使用样式渗透来生效。我们可以使用 >>> 或者 /deep/ 来解决这个问题:


   
  1. <style scoped>
  2. Outer layer >>> .el-checkbox {
  3. display: block;
  4. font-size: 26px;
  5. .el-checkbox__label {
  6. font-size: 16px;
  7. }
  8. }
  9. </style>

   
  1. <style scoped>
  2. /deep/ .el-checkbox {
  3. display: block;
  4. font-size: 26px;
  5. .el-checkbox__label {
  6. font-size: 16px;
  7. }
  8. }
  9. </style>

4.watch的高级使用

watch 在监听器属性发生变化时触发,有时我们希望 watch 在组件创建后立即执行。可能想到的方式是在创建生命周期中调用它一次,但这不是一种优雅的编写方式,所以也许我们可以使用这样的东西。


   
  1. export default {
  2. data() {
  3. return {
  4. name: Joe
  5. }
  6. },
  7. watch: {
  8. name: {
  9. handler: sayName ,
  10. immediate: true
  11. }
  12. },
  13. methods: {
  14. sayName() {
  15. console.log(this.name)
  16. }
  17. }
  18. }

Deep Listening

监听一个对象时,当对象内部的属性发生变化时,watch是不会被触发的,所以我们可以为它设置深度监听


   
  1. export default {
  2. data: {
  3. studen: {
  4. name: Joe ,
  5. skill: {
  6. run: {
  7. speed: fast
  8. }
  9. }
  10. }
  11. },
  12. watch: {
  13. studen: {
  14. handler: sayName ,
  15. deep: true
  16. }
  17. },
  18. methods: {
  19. sayName() {
  20. console.log(this.studen)
  21. }
  22. }
  23. }

触发监听器执行多个方法

使用数组,您可以设置多个形式,包括字符串、函数、对象。


   
  1. export default {
  2. data: {
  3. name: Joe
  4. },
  5. watch: {
  6. name: [
  7. sayName1 ,
  8. function(newVal, oldVal) {
  9. this.sayName2()
  10. },
  11. {
  12. handler: sayName3 ,
  13. immaediate: true
  14. }
  15. ]
  16. },
  17. methods: {
  18. sayName1() {
  19. console.log( sayName1==> , this.name)
  20. },
  21. sayName2() {
  22. console.log( sayName2==> , this.name)
  23. },
  24. sayName3() {
  25. console.log( sayName3==> , this.name)
  26. }
  27. }
  28. }

5.watch监听多个变量

watch 本身不能监听多个变量。但是,我们可以通过返回具有计算属性的对象然后监听该对象来“监听多个变量”。


   
  1. export default {
  2. data() {
  3. return {
  4. msg1: apple ,
  5. msg2: banana
  6. }
  7. },
  8. compouted: {
  9. msgObj() {
  10. const { msg1, msg2 } = this
  11. return {
  12. msg1,
  13. msg2
  14. }
  15. }
  16. },
  17. watch: {
  18. msgObj: {
  19. handler(newVal, oldVal) {
  20. if (newVal.msg1 != oldVal.msg1) {
  21. console.log( msg1 is change )
  22. }
  23. if (newVal.msg2 != oldVal.msg2) {
  24. console.log( msg2 is change )
  25. }
  26. },
  27. deep: true
  28. }
  29. }
  30. }

6.事件参数$event

$event 是事件对象的一个特殊变量,它在某些场景下为我们提供了更多的可用参数来实现复杂的功能。本机事件:与本机事件中的默认事件对象行为相同。


   
  1. <template>
  2. <div>
  3. <input type="text" @input="inputHandler( hello , $event)" />
  4. </div>
  5. </template>

   
  1. export default {
  2. methods: {
  3. inputHandler(msg, e) {
  4. console.log(e.target.value)
  5. }
  6. }
  7. }

自定义事件:在自定义事件中表示为捕获从子组件抛出的值。


   
  1. export default {
  2. methods: {
  3. customEvent() {
  4. this.$emit( custom-event , some value )
  5. }
  6. }
  7. }

   
  1. <template>
  2. <div>
  3. <my-item v-for="(item, index) in list" @custom-event="customEvent(index, $event)">
  4. </my-list>
  5. </div>
  6. </template>

   
  1. export default {
  2. methods: {
  3. customEvent(index, e) {
  4. console.log(e) // some value
  5. }
  6. }
  7. }

7.程序化事件监听器

例如,在页面挂载时定义一个定时器,需要在页面销毁时清除定时器。这似乎不是问题。但仔细观察,this.timer 的唯一目的是能够在 beforeDestroy 中获取计时器编号,否则是无用的。


   
  1. export default {
  2. mounted() {
  3. this.timer = setInterval(() => {
  4. console.log(Date.now())
  5. }, 1000)
  6. },
  7. beforeDestroy() {
  8. clearInterval(this.timer)
  9. }
  10. }

如果可能,最好只访问生命周期挂钩。这不是一个严重的问题,但可以认为是混乱。我们可以通过使用 或once 监听页面生命周期销毁来解决这个问题:


   
  1. export default {
  2. mounted() {
  3. this.creatInterval( hello )
  4. this.creatInterval( world )
  5. },
  6. creatInterval(msg) {
  7. let timer = setInterval(() => {
  8. console.log(msg)
  9. }, 1000)
  10. this.$once( hook:beforeDestroy , function() {
  11. clearInterval(timer)
  12. })
  13. }
  14. }

使用这种方法,即使我们同时创建多个定时器,也不影响效果。这是因为它们将在页面被销毁后以编程方式自动清除。8.监听组件生命周期通常我们使用 $emit 监听组件生命周期,父组件接收事件进行通知。

子组件


   
  1. export default {
  2. mounted() {
  3. this.$emit( listenMounted )
  4. }
  5. }

父组件


   
  1. <template>
  2. <div>
  3. <List @listenMounted="listenMounted" />
  4. </div>
  5. </template>

其实有一种简单的方法就是使用@hook 来监听组件的生命周期,而不需要在组件内部做任何改动。同样,创建、更新等也可以使用这个方法。


   
  1. <template>
  2. <List @hook:mounted="listenMounted" />
  3. </template>

转载:https://blog.csdn.net/m0_64460287/article/details/128906936
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场