Vue开发技巧总结(四)图片加载失败、组件级路由钩子、递归组件、路由参数解耦、install自定义组件

img图片加载失败

场景:有些时候后台返回的图片不一定能加载成功,加载失败默认显示一张图片

<template>
  <div>
    <img :src="imgUrl" @error="handleError" alt="">
  </div>
</template>

<script>
export default {
  data () {
    return {
      imgUrl: ''
    }
  },
  methods: {
    handleError (e) {
      e.target.src = require('@/assets/logo.png')
    }
  }
}
</script>

组件级路由钩子

beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被确认前调用
  console.log(to)
  console.log(from)
  next()
},
beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由调用
  next()
}

递归组件

场景:如果开发一个 tree 组件,里面层级是根据后台数据决定的,这个时候就需要用到动态组件

  • 递归组件: 组件在它的模板内可以递归的调用自己,只要给组件设置name组件就可以了。
  • 设置那么House在组件模板内就可以递归使用了,不过需要注意的是,
  • 必须给一个条件来限制数量,否则会抛出错误: max stack size exceeded
  • 组件递归用来开发一些具体有未知层级关系的独立组件。比如:联级选择器和树形控件

父组件:

<template>
  <div>
    <Tree :treeArr="treeArr"></Tree>
  </div>
</template>

<script>
import Tree from './tree.vue'
export default {
  components: {
    Tree
  },
  data () {
    return {
      imgUrl: '',
      treeArr: [
        {
          id: 1,
          expand: true,
          name: '二级节点1',
          children: [{
            id: 12,
            expand: true,
            name: '三级节点1'
          }]
        },
        {
          id: 2,
          expand: true,
          name: '二级节点2',
          children: [{
            id: 21,
            expand: true,
            name: '三级节点2'
          }]
        }
      ]
    }
  }
}
</script>

子组件:

<template>
  <div>
    <div v-for="(item, index) in treeArr">
      <div :key="item.id">
        {{item.name}}
        <!-- 递归调用自身,后台判断是否存在该值 -->
        <Tree :treeArr="item.children" v-if="item.expand"></Tree>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Tree', // 必须定义name,组件内部递归使用
  props: {
    treeArr: {
      type: Array,
      default: () => []
    }
  }
}
</script>

路由参数解耦

  1. 一般在组件内使用路由参数,大多数人会这样做:

    export default {
        methods: {
            getParamsId() {
                return this.$route.params.id
            }
        }
    }
    
  2. 正确的做法是通过 props 解耦

    const router = new VueRouter({
        routes: [{
            path: '/user/:id',
            component: User,
            props: true
        }]
    })
    

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

export default {
    props: ['id'],
    methods: {
        getParamsId() {
            return this.id
        }
    }
}
  1. 还可以通过函数模式来返回 props

    const router = new VueRouter({
        routes: [{
            path: '/user/:id',
            component: User,
            props: (route) => ({
                id: route.query.id
            })
        }]
    })
    

Router key

由于 Vue 会复用相同组件,例如 /page?id=1 => /page?id=2 这类跳转的情况,组件将不会执行 created, mounted 等钩子函数,此时常用解决方案如下。

watch监听

watch: {
  $route (to, from) {
    console.log(to, '....') // 可以监听到路由的变化,例如从详情1跳转到详情2
  }
},

给 router-view 绑定一个 unique key

// $route.fullPath: 完成解析后的 URL,包含查询参数和 hash 的完整路径
<router-view :key="$route.fullPath"></router-view>

注:如果没有类似的场景不建议使用,毕竟每次渲染还是要付出一丢丢性能代价的。

通过Vue.use()使用install创建自定义组件

  1. 首先新建loading文件夹,并在文件夹内新建loading.vue和index.js文件

    <template>
        <div>
            Loading....
        </div>
    </template>
    
  2. 编辑index.js,核心为install属性,

    import LoadingComponent from './Loading'
    
    const Loading = {
        install: (Vue) => {
            Vue.component('Loading', LoadingComponent)
        }
    }
    
    export default Loading
    
  3. main.js中引入相应的组件并用vue.use()使用组件

    import Loading from '@/components/index'
    Vue.use(Loading)
    

统一处理方式

index.js

import LoadingComponent from '@/components/Loading'

const customCom = (Vue) => {
    const Loading = {
        install: () => {
            Vue.component('Loading', LoadingComponent)
        }
    }
    Vue.use(Loading)
}

export default customCom

main.js

import customCom from './components/index.js'
customCom(Vue)

你可能感兴趣的:(vue)