vue高级开发的技巧

  • 1.在v-for中使用函数
  • 2.使用Object.assign进行多个响应式属性赋值
  • 3.使用修饰符.passive提升移动端性能
  • 4.使用inheritAttrs:false禁止属性集成,但是不影响class和style的合并
  • 5.使用@hook:生命周期来优化代码,增加可维护性
  • 6.小型项目采用vue2.6提供的新API Vue.observable手动打造一个小型Vuex
  • 7.使用Vue.extend开发一些全局组件比如Loading,Notify,Message等组件,进行手动挂载
  • 8.使用自定义指令让组件更灵活
  • 9.使用$watch函数随时监听,随时取消
  • 10.对于纯展示型组件采用函数式组件提升性能
  • 11.小型项目使用$bus进行通讯
  • 12.自定义封装v-model组件
  • 13.作用于插槽的使用
  • 14.vue对于长列表渲染的性能优化
  • 15.watch监听多个data
  • 16.解耦路由参数
  • 17.巧用作用域插槽
  • 18.vue列表的动画效果
  • 19.在对组件进行二次封装时,可以使用$attrs实现属性透传
  • 20.动态组件如何实现属性透传
  • 21.动态指令参数—>我们可以动态的为一个元素绑定不同的事件
  • 22.CSS scoded 和深度作用选择器
  • 23.使用v-cloak解决页面闪烁问题
  • 24.v-once 和 v-pre 提升性能
  • 25.在template中打log
  • 26.自定义prop的校验器
  • 27.巧用es6的解构赋值简化vue代码
  • 28.怎样在vue中使用jsx
  • 29.怎样解决路由参数变化组件不更新的问题
  • 30.vue中路由懒加载的3种方式
  • 31.使用.sync来简化父子组件的通讯
  • 32.将一个 prop 限制在一个类型的列表中
  • 33.使用引号来监听嵌套属性
  • 34. 如何监听一个插槽内容的变化
  • 35.在v-for中使用解构
  • 36.窃取子组件定义的props类型
  • 37.组件的元数据

1.在v-for中使用函数
在这里插入图片描述
2.使用Object.assign进行多个响应式属性赋值
在这里插入图片描述
3.使用修饰符.passive提升移动端性能
在这里插入图片描述
3.使用inheritAttrs:false禁止属性集成,但是不影响class和style的合并
在这里插入图片描述
4.使用.sync来简化父子组件的通讯
在这里插入图片描述
5.使用@hook:生命周期来优化代码,增加可维护性

  • 将绑定监听函数和解绑监听函数写到同一个钩子中,便于维护
    在这里插入图片描述
  • 在组件外部监听组件的生命周期,而不需要改动组件逻辑
    在这里插入图片描述
    6.小型项目采用vue2.6提供的新API Vue.observable手动打造一个小型Vuex
    在这里插入图片描述
    在这里插入图片描述
    7.使用Vue.extend开发一些全局组件比如Loading,Notify,Message等组件,进行手动挂载
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    8.使用自定义指令让组件更灵活
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
import Vue from 'vue'
import LoadingComponent from './loading'
// 使用 Vue.extend构造组件子类
const LoadingContructor = Vue.extend(LoadingComponent)

// 定义一个名为loading的指令
Vue.directive('loading', {
  /**
   * 只调用一次,在指令第一次绑定到元素时调用,可以在这里做一些初始化的设置
   * @param {*} el 指令要绑定的元素
   * @param {*} binding 指令传入的信息,包括 {name:'指令名称', value: '指令绑定的值',arg: '指令参数 v-bind:text 对应 text'}
   */
  bind(el, binding) {
    const instance = new LoadingContructor({
      el: document.createElement('div'),
      data: {}
    })
    el.appendChild(instance.$el)
    el.instance = instance
    Vue.nextTick(() => {
      el.instance.visible = binding.value
    })
  },
  /**
   * 所在组件的 VNode 更新时调用
   * @param {*} el
   * @param {*} binding
   */
  update(el, binding) {
    // 通过对比值的变化判断loading是否显示
    if (binding.oldValue !== binding.value) {
      el.instance.visible = binding.value
    }
  },
  /**
   * 只调用一次,在 指令与元素解绑时调用
   * @param {*} el
   */
  unbind(el) {
    const mask = el.instance.$el
    if (mask.parentNode) {
      mask.parentNode.removeChild(mask)
    }
    el.instance.$destroy()
    el.instance = undefined
  }
})

在这里插入图片描述
9.使用$watch函数随时监听,随时取消
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
10.对于纯展示型组件采用函数式组件提升性能
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

11.小型项目使用$bus进行通讯
在这里插入图片描述
在这里插入图片描述
12.自定义封装v-model组件

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:

<template>
  <div class="amir--select">
    <select
      :value="selected"
      class="amir--select__item"
      :disabled="readonly"
      @change="emitChange($event.target.value)"
    >
      <template v-for="(item,index) in selectData">
        <option
          :key="index"
          :value="item.value"
        >
          {{ item.text }}
        </option>
      </template>
    </select>
  </div>
</template>

<script>
export default {
  name: 'ASelect',
  model: {
    prop: 'selected', //指定value的别名
    event: 'change' //指定input事件的别名
  },
  props: {
    selectData: {
      type: Array
    },
    readonly: {
      type: Boolean,
      default: false
    },
    selected: {
      type: [String, Number]
    }
  },
  methods: {
    emitChange (value) {
      this.$emit('change', value)
    }
  }
}
</script>

<style lang="less">
</style>

13.作用于插槽的使用
在这里插入图片描述
在这里插入图片描述
14.vue对于长列表渲染的性能优化
在这里插入图片描述
15.watch监听多个data
在这里插入图片描述
16.解耦路由参数
在这里插入图片描述
在这里插入图片描述
17.巧用作用域插槽
在这里插入图片描述
在这里插入图片描述
18.vue列表的动画效果
源代码

19.在对组件进行二次封装时,可以使用$attrs实现属性透传
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
20.动态组件如何实现属性透传

config.vue—>动态渲染组件的父级容器

<template>
  <div class="hello">
    <div v-for="(config, index) in configJsonArr" :key="config.type + index">
      <!-- <component :is="config.type" :configProps="config.props"></component> -->
      <comp-form-item :configJson="config"></comp-form-item>
    </div>
  </div>
</template>

<script>
import Input from './Input'
import Select from './Select'

const CompFormItem = {
  components: {
    Input, Select
  },
  name: 'FormItem',
  props: {
    configJson: {
      required: true
    }
  },
  render (h) {
    return h(`${this.configJson.type}`, {
      props: {
        ...this.configJson.props || {}
      },
      attrs: {
        ...this.configJson.props || {}
      }
    })
  }
}

export default {
  name: 'Config',
  components: {
    // Input,
    // Select,
    CompFormItem
  },
  props: {
    configJsonArr: {
      type: Array,
      required: true,
      default: () => []
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Input.vue---->第一个动态组件

<template>
  <div class="hello input-con">
    <label>输入框:</label>
    <el-input v-bind="$attrs"></el-input>
  </div>
</template>

<script>
export default {
  name: 'Input'
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.input-con {
  margin: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  label {
    width: 200px;
  }
}
</style>

Select.vue—>第二个动态组件

<template>
  <div class="hello select-con">
    <label>选择框:</label>
    <el-select v-bind="$attrs" v-model="value"></el-select>
  </div>
</template>

<script>
export default {
  name: 'Select',
  data () {
    return {
      value: ''
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.select-con {
  margin: 20px;
  display: flex;
  align-items: center;
  label {
    width: 170px;
  }
}
</style>

21.动态指令参数—>我们可以动态的为一个元素绑定不同的事件
在这里插入图片描述
22.CSS scoded 和深度作用选择器
在这里插入图片描述
在这里插入图片描述
23.使用v-cloak解决页面闪烁问题
在这里插入图片描述
24.v-once 和 v-pre 提升性能
在这里插入图片描述
25.在template中打log(控制台可以查看结果)
在这里插入图片描述
也可以使用<pre>{{data}}</pre>标签将数据显示到页面上

26.自定义prop的校验器
在这里插入图片描述
27.巧用es6的解构赋值简化vue代码
在这里插入图片描述
在这里插入图片描述
28.怎样在vue中使用jsx

babel配置链接

官方使用文档
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对比渲染函数和jsx,以下两幅图是等价的

1.渲染函数
在这里插入图片描述
2.jsx
在这里插入图片描述
29.怎样解决路由参数变化组件不更新的问题

同一path的页面跳转时路由参数变化,但是组件没有对应的更新。

原因:主要是因为获取参数写在了created或者mounted路由钩子函数中,路由参数变化的时候,这个生命周期不会重新执行。
在这里插入图片描述
在这里插入图片描述
30.vue中路由懒加载的3种方式
在这里插入图片描述
31.将一个 prop 限制在一个类型的列表中
使用 prop 定义中的 validator 选项,可以将一个 prop 类型限制在一组特定的值中。

export default {
  name: 'Image',
  props: {
    src: {
      type: String,
    },
    style: {
      type: String,
      validator: s => ['square', 'rounded'].includes(s)
    }
  }
};

这个验证函数接受一个prop,如果prop有效或无效,则返回true或false。

当单单传入的 true 或 false 来控制某些条件不能满足需求时,我通常使用这个方法来做。

按钮类型或警告类型(信息、成功、危险、警告)是最常见的用法、、。颜色也是一个很好的用途。

32.使用引号来监听嵌套属性

watch {
  '$route.query.id'() {
    // ...
  }
}
  1. 如何监听一个插槽内容的变化
    Vue没有内置的方法让我们检测这一点

MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分。

export default {
  mounted() {
    // 当有变化时调用`update`
    const observer = new MutationObserver(this.update);

    // 监听此组件的变化
    observer.observe(this.$el, {
      childList: true,
      subtree: true
    });
  }
};

34.在v-for中使用解构

<template>
  <div id="app">
    <div
      v-for="{name,age} in users"
      :key="age"
    >
      {{ name }}+{{ age }}
    </div>
  </div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  data () {
    return {
      users: [
        { name: '11', age: 23 },
        { name: '22', age: 44 }
      ]
    }
  }
})
</script>

35.窃取子组件定义的props类型

我从一个子组件中复制 prop 类型,只是为了在一个父组件中使用它们。但我发现,偷取这些 prop 类型要比仅仅复制它们好得多。

例如,我们在这个组件中使用了一个Icon组件。

<template>
  <div>
    <h2>{{ heading }}</h2>
    <Icon
      :type="iconType"
      :size="iconSize"
      :colour="iconColour"
    />
  </div>
</template>

为了让它工作,我们需要添加正确的 prop 类型,从Icon组件复制。

import Icon from './Icon';
export default {
  components: { Icon },
  props: {
    iconType: {
      type: String,
      required: true,
    },
    iconSize: {
      type: String,
      default: 'medium',
      validator: size => [
        'small',
        'medium',
        'large',
        'x-large'
      ].includes(size),
    },
    iconColour: {
      type: String,
      default: 'black',
    },
    heading: {
      type: String,
      required: true,
    },
  },
};

当 Icon 组件的 prop类型被更新时,我们肯定会忘记返回这个组件并更新它们。随着时间的推移,当该组件的 prop类型开始偏离Icon组件中的 prop 类型时,就会引入错误。

因此,这就是为什么我们要窃取组件的 prop 类型:

import Icon from './Icon';
export default {
  components: { Icon },
  props: {
    ...Icon.props,
    heading: {
      type: String,
      required: true,
    },
  },
};

不需要再复杂了。

除了在我们的例子中,我们把 icon 加在每个 prop 名称的开头。所以我们必须做一些额外的工作来实现这一点。

import Icon from './Icon';

const iconProps = {};

Object.entries(Icon.props).forEach((key, val) => {
  iconProps[`icon${key.toUpperCase()}`] = val;
});

export default {
  components: { Icon },
  props: {
    ...iconProps,
    heading: {
      type: String,
      required: true,
    },
  },
};

现在,如果Icon组件中的 prop 类型被修改,我们的组件将保持最新状态。

但是,如果一个 prop 类型从 Icon 组件中被添加或删除了呢?为了应对这些情况,我们可以使用v-bind和一个计算的 prop 来保持动态。

  1. 组件的元数据
    并不是添加到一个组件的每一点信息都是状态。有时我们需要添加一些元数据,给其他组件提供更多信息。

例如,如果正在为谷歌 analytics这样的分析仪表:
在这里插入图片描述
如果你想让布局知道每个小组件应该占多少列,你可以直接在组件上添加元数据。

export default {
  name: 'LiveUsersWidget',
  // 👇 只需将其作为一个额外的属性添加
  columns: 3,
  props: {
    // ...
  },
  data() {
    return {
      //...
    };
  },
};

你会发现这个元数据是组件上的一个属性。


import LiveUsersWidget from './LiveUsersWidget.vue';
const { columns } = LiveUsersWidget;
我们也可以通过特殊的$options属性从组件内部访问元数据。

export default {
  name: 'LiveUsersWidget',
  columns: 3,
  created() {
    // 👇 `$options` contains all the metadata for a component
    console.log(`Using ${this.$options.metadata} columns`);
  },
};

只要记住,这个元数据对组件的每个实例都是一样的,而且不是响应式的。

这方面的其他用途包括(但不限于):

  • 保持单个组件的版本号
  • 用于构建工具的自定义标志,以区别对待组件
  • 在计算属性、数据、watch 等之外为组件添加自定义功能
  • 其它
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue 2 中的高级组件开发可以通过 mixin、插槽和自定义指令等技术来实现。下面是一些常见的技巧: 1. Mixin:Mixin 是一种重用组件逻辑的方式。通过将常用的选项合并到 mixin 对象中,然后在组件中使用 mixins 选项来引入 mixin。这样可以有效地提高代码的复用性。例如,您可以创建一个 mixin 对象,包含一些常用的方法和生命周期钩子函数,然后在需要的组件中引入。 2. 插槽(Slot):插槽是一种在父组件中向子组件传递内容的方式。通过在父组件中使用<slot>标签,并在子组件中使用<slot>标签的 name 属性来定义插槽。这样可以实现组件的灵活性,使父组件能够根据需要向子组件传递不同的内容。 3. 自定义指令(Custom Directive):自定义指令是一种在 HTML 元素上添加特定行为的方式。通过使用 Vue.directive 函数来定义一个全局的指令,然后在模板中使用 v-directive 指令来调用。自定义指令可以用于处理 DOM 元素的事件、样式、属性等。 4. 动态组件(Dynamic Component):动态组件允许您根据条件渲染不同的组件。通过使用<component>标签并通过 is 属性来指定要渲染的组件,可以根据需要切换不同的组件。 5. 渲染函数(Render Function):Vue 2 中可以使用 render 函数来编写组件的模板。使用 render 函数可以实现更灵活、动态的组件渲染。通过编写 JavaScript 代码来生成组件的虚拟 DOM 树,并将其返回给 Vue 实例进行渲染。 这些是一些基本的高级组件开发技巧Vue 2 还提供了更多强大的特性和工具,您可以根据具体需求进一步深入学习和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值