详解Vue文档中几个易忽视部分的剖析

针对Vue文档中部分大家可能不会去研读的内容,我做了个小总结,作为有经验者的快餐,不是特别适合初学者,可能有不妥之处,希望大家多提建议。

节省代码量的mixin

mixin概念:组件级可复用逻辑,包括数据变量/生命周期钩子/公共方法,从而在混入的组件中可以直接使用,不用重复写冗余逻辑(类似继承)

使用方法:

在某一公共文件夹pub下创建mixin文件夹,其下创建mixinTest.js

const mixinTest = {
  created() {
    console.log(`components ${this.name} created`)
  },
  methods: {
    hello() {
      console.log('mixin method hello')
    }
  }
}
export default mixinTest

在组件中引用刚才的公共混入文件并使用

import mixinTest from '../pub/mixin/mixinTest.js'
export default {
  data() {
    return {
      name: 'hello'
    }
  },
  mixins: [mixinTest],
  methods: {
    useMixin() {
      this.hello()
    }
  }
}

ps: 若是使用Vue.mixin()这个方法,则会影响之后创建的所有Vue示例,慎用!

注意mixin的几个特性:

  1. 混入的数据变量是浅合并,冲突时以组件内的数据优先(对象里面的自定义变量)
  2. 混入的生命周期函数内的逻辑会与组件内定义的生命周期函数逻辑进行合并,并且先执行(created/mounted/destroy)
  3. 混入的值为对象的选项,会混合成一个对象,冲突后也是以组件内键名优先(data/method/components/directives)

slot内容分发

slot概念引入:Vue跟React在写法上的不同就在于组件与子组件内部元素的组织上,在组件里面没有children元素供我们访问和展现(暂不考虑render函数),取而代之的API是slot

使用场景定义:

  1. 自定义的子组件里面有嵌套的HTML或者其他自定义的标签组件
  2. 这个自定义的子组件是写在父组件里面,嵌套的东西也放在父组件里面
  3. 通过在子组件的模板里面使用<slot></slot>标签,从而达到渲染写在父组件里的嵌套标签的效果
  4. 本质是把父组件放在子组件里的内容,插到了子组件的位置,多个标签也会一起被插入
<template>
  <div id="app">
    <self-component> <!--self-component表示自定义的组件-->
      <span>12345</span> <!--父组件里的嵌套标签-->
    </self-component>
  </div>
</template>
<script>
export default {
  components: [selfComponent]
}
</script>

<!--self-component的组件模板-->
<template>
  <div>
    <button><slot></slot></button>
  </div>
</template>
<script>
export default {
  // 只有子组件的模板里面有slot标签,才能取到写在自定义组件里面的标签的渲染引用
}
</script>

slot特性的进阶两点:

slot插入内容的编译作用域:被分发的内容的作用域,根据其所在模板决定

  1. 具体内容写的位置,决定了编译的作用域(大部分情况都是在父组件作用域下)
  2. 2.1.0+新增作用域插槽,从而可以把子组件的属性暴露给父组件中写在子组件内的内容使用
  3. 子组件中的slot标签可以直接写自定义属性,然后父组件写在slot中的标签加上slot-scope属性
<!-- 父组件模板 -->
<child :items="items">
 <!-- 作用域插槽也可以是具名的 -->
 <li slot="item" slot-scope="props" class="my-fancy-item">{{ props.text }}</li>
</child>

<!-- 子组件模板 -->
<ul>
 <slot name="item" v-for="item in items" :text="item.text">
  <!-- 这里写当父组件引用子组件但没写内部内容时展示的东东 -->
 </slot>
</ul>

slot的name属性来指定标签插入的位置,也就是文档里面的具名插槽(这个官方文档说的明白)

  1. 在子组件的模板里面写的slot有个name属性(<slot name="foo"></slot>)
  2. 在父组件中写子组件里面的插槽内容,指明slot属性(<p slot="foo">123</p>)
  3. 父组件的内容就会对应slot==name放到正确的位置
  4. 没有指明slot属性的就会默认放到匿名插槽的位置上

动态组件

动态组件这个特性,很多人写的Vue项目也不少,但也没用到过这个,有必要多说几句

动态组件适用情况:

  1. 单页应用,部分组件的切换不涉及路由,只是页面有一块区域的组件要变更
  2. 变更的组件参数定义上是一致的,比如都是对话框,要传一个对象进去,但对象里面的数据结构不同
  3. 通过使用component的is属性,避免在template中的冗余组件代码,避免多个v-if模板代码更加整洁

使用的方法(借鉴文档):

<keep-alive>
  <component v-bind:is="currentView">
  <!-- 组件在 vm.currentview (对应组件名称)变化时改变! -->
  <!-- 非活动组件将被缓存!可以保留它的状态或避免重新渲染 -->
  </component>
</keep-alive>

注意点:

  1. 动态切换的组件都要引入到父组件中,渲染是动态的,但引入不是。
  2. <keep-alive>包裹动态组件时,会缓存不活动的组件实例,提高性能,避免重复渲染(keep-alive不会渲染额外DOM结构)
  3. <keep-alive>有include和exclude这两个属性,用于指定缓存和不缓存的组件(传入字符串/数组/正则)
  4. 另一种避免重新渲染的方法是为标签增加属性v-once,用于缓存大量的静态内容,避免重复渲染。

ps:<keep-alive>不会在函数式组件中正常工作,因为它们没有缓存实例。

动画与过渡

其实很多前端工程师第一次用Vue的动画和过渡都是通过库组件来做到的,所以对这块没怎么深挖,各种过渡特效和按钮动画就跑起来了,现在就看下文档,补补课

前端实现动画的基本方法分为三种种:css3的过渡和keyframe/javascript操纵dom/使用webgl或者canvas来独立实现,其中第三种是作为展示动画,与交互结合较少,而Vue作为一个框架,其支持动画基是从前两种入手的,从官方文档提到的四种支持就可以看出这一点。不过官方文档是从DOM过渡和状态过渡两个方面来讲解,前者是DOM的消失和出现的动画等属性的变化,后者是页面上某些值的变化。

DOM属性的改变

若是单个元素/组件的显隐,在组件外面包裹一层<transition></transition>,而后选择是css过渡还是javascript过渡

CSS过渡:

  1. vue提供了六个样式后缀,本质是在dom过渡的过程中动态地添加和删除对应的className。(-[enter|leave]-?[active|to]?)
  2. 如果用css库来辅助开发,可以在transiton这个标签上定义自定义过渡类名,也是六个属性。([enter|leave]-?[active|to]?-class)
  3. 常见的一种效果是元素首次渲染的动画,如懒加载图片飞入,这个时候要在transiton标签上加上appear,另有三个属性可指定(appear-?[to|active]?-class)
<!-- 每种CSS动画库对应的class命名规则可能不同,所以根据不同库要自己写,以animate.css为例 -->
<transition
  name="custom-classes-transition"
  enter-active-class="animated tada"
  leave-active-class="animated bounceOutRight"
  :duration="{ enter: 500, leave: 800 }"
>...</transition>
<!-- duration属性可以传一个对象,定制进入和移出的持续时间-->

JS过渡:

  1. 因为现在很多动画库需要工程师调用库提供的函数,把dom元素传入进行处理,这个时候需要这种方式
  2. 通过在transiton这个标签上添加监听事件,共8个([before|after]?-?[enter|leave]-?[cancelled]?)
  3. 监听事件的回调函数的第一个参数都是el,为过渡的dom元素,在enter和leave这两个还会传入done作为第二个参数
  4. 元素首次渲染的动画,可以指定的监听事件有4个([before|after]?-?appear和appear-cancelled)
<template>
  <transition v-bind:css="false"
  v-on:before-enter="beforeEnter" v-on:enter="enter"
  v-on:leave="leave" v-on:leave-cancelled="leaveCancelled">
    <!-- 对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测 -->
  </transition>
</template>
<script>
methods: { // 以Velocity库为例
  beforeEnter: function (el) {/*...*/},
 // 此回调函数是可选项的设置
 enter: function (el, done) {
  // Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
  done() //回调函数 done 是必须的。否则,它们会被同步调用。
 },
 leave: function (el, done) {
  // Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
  done()
 },
 leaveCancelled: function (el) {/*...*/}
}
</script>

多元素过渡其实就是一句话:照常使用v-if/v-else的同时对同一种标签加上key来标识

Vue对于这种多元素动画有队列上的处理,这就是transiton这个标签上的mode属性,通过指定(in-out|out-in)模式,实现消失和出现动画的队列效果,让动画更加自然。

<transition name="fade" mode="out-in">
 <!-- ... the buttons ... -->
</transition>

多组件过渡也是一句话:用上一节提到的动态组件,即可完成。

针对列表过渡,其本质仍是多个元素的同时过渡,不过列表大部分是通过数组动态渲染的,因此有独特的地方,不过整体的动画思路不变。具体有以下几点

  1. 使用transitoin-group这个组件,其需要渲染为一个真实元素,可以通过tag这个属性来指定。
  2. 列表的每个元素需要提供key属性
  3. 使用CSS过渡的话,要考虑到列表内容变化过程中,存在相关元素的定位改变,如果要让定位是平滑过渡的动画,要另外一个v-move属性。 这个属性是通过设置一个css类的样式,来将创建元素在定位变化时的过渡,Vue内部是通过FLIP实现了一个动画队列,只要注意一点就是过渡元素不能设置为display:inline,这里需要文档上的代码做一个简短的demo:(其实通过在li上设置过渡transition属性也可以实现v-move的效果)
<template>
  <button v-on:click="shuffle">Shuffle</button>
  <transition-group name="flip-list" tag="ul">
    <li v-for="item in items" v-bind:key="item">{{ item }}</li>
  </transition-group>
</template>
<script>
import _ from 'lodash';
export default {
  data() {
    return {
      items: [1,2,3,4,5,6,7,8,9]
    }
  },
  methods: {
    shuffle: function () {
      this.items = _.shuffle(this.items)
    }
  }
}
</script>
<style lang="css">
.flip-list-move {
 transition: transform 1s;
}
</style>

数值和属性动态变化

这一部分的动画主要是针对数据元素本身的特效,比如数字的增减,颜色的过渡过程控制,svg动画的实现等,其本质都是数字/文本的变化。 我自己总结就是:通过利用Vue的响应式系统,把数字的变化通过外部库把DOM上对应数值的变化做出连续的效果,如1->100是个数字递增的连续过程,黑色->红色的过程。官方文档主要是用几个示例代码来说明,其本质步骤如下:

  1. 在页面上通过input的双向绑定修改某一变量a,还有一个处理dom上的过渡效果的变量b
  2. 这个数据被watcher绑定(watch对象中某个属性是这个变量a),触发逻辑
  3. 在watcher里面的逻辑就是通过外部过渡库,指定初始值b和最终值a,是把b的值最后改为a
  4. DOM上绑定的变量就是b,如果某些复杂情况可能是基于b的计算属性,从而把b的变化过程展现出来

上面这个思路走一遍下来就完成了一个单元级别的动画效果,这种类似的流程其实是很常见的需求,所以有必要把这个过程封装成一个组件,只暴露要过渡的值作为入口,每次改变这个值都是一个动画过渡效果。组件封装需要在上面四个步骤的基础上添加mounted生命周期规定初始值即可,同时原来的两个值a/b在组件里面作为一个值,可以用watch对象中的newValue和oldValue作为区分。   至于最后的SVG,其本质也是数字的过渡,只不过里面涉及的状态变量更多,代码更长而已,不过纯前端页面这种需求倒还是不多的,不过作为爱好倒可以鼓捣一些好玩的小demo,不过肯定需要设计师的参与,要不那些参数可不好调出来呐。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • vuex 使用文档小结篇
  • 深入理解Vue官方文档梳理之全局API
  • Vue官方文档梳理之全局配置
  • 详解vue axios中文文档
  • 详解vue前后台数据交互vue-resource文档
(0)

相关推荐

  • 详解vue axios中文文档

    axios中文文档 在用Vue做开发的时候,官方推荐的前后端通信插件是axios,Github上axios的文档虽然详细,但是却是英文版.现在发现有个axios的中文文档,于是就转载过来了! 原文地址 : https://github.com/mzabriskie/axios 简介 版本:v0.16.1 基于http客户端的promise,面向浏览器和nodejs 特色 浏览器端发起XMLHttpRequests请求 node端发起http请求 支持Promise API 拦截请求和返回 转化请

  • 深入理解Vue官方文档梳理之全局API

    Vue.extend 配置项data必须为function,否则配置无效.data的合并规则(可以看<Vue官方文档梳理-全局配置>)源码如下: 传入非function类型的data(上图中data配置为{a:1}),在合并options时,如果data不是function类型,开发版会发出警告,然后直接返回了parentVal,这意味着extend传入的data选项被无视了. 我们知道实例化Vue的时候,data可以是对象,这里的合并规则不是通用的吗?注意上面有个if(!vm)的判断,实例化

  • 详解vue前后台数据交互vue-resource文档

    这两天学习了vue-resource插件个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记. Vue可以构建一个完全不依赖后端服务的应用,同时也可以与服务端进行数据交互来同步界面的动态更新. Vue通过插件的形式实现了基于AJAX,JSPNP等技术的服务端通信. vue-resource是一个通过XMLHttpRequrest或JSONP技术实现异步加载服务端数据的Vue插件 提供了一般的 HTTP请求接口和RESTful架构请求接口,并且提供了全局方法和VUe组件实例方法. 使用的版本是

  • Vue官方文档梳理之全局配置

    本文主要介绍了Vue官方文档梳理之全局配置,分享给大家,也给自己留个笔记.具体如下: optionMergeStrategies 用于自定义选项的合并策略,Vue已经预定义了一些自己配置项的合并策略,如下图所示. 比如props.methods.computed就是同一个策略:子配置项会覆盖父级配置项.源码如下: var strats = config.optionMergeStrategies; strats.props = strats.methods = strats.computed =

  • vuex 使用文档小结篇

    Vuex是什么? Vuex 是一个专为 Vue.js应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel调试.状态快照导入导出等高级调试功能. 安装 直接下载CDN 引用 <script src="/path/to/vue.js"></script> <script s

  • 详解Vue文档中几个易忽视部分的剖析

    针对Vue文档中部分大家可能不会去研读的内容,我做了个小总结,作为有经验者的快餐,不是特别适合初学者,可能有不妥之处,希望大家多提建议. 节省代码量的mixin mixin概念:组件级可复用逻辑,包括数据变量/生命周期钩子/公共方法,从而在混入的组件中可以直接使用,不用重复写冗余逻辑(类似继承) 使用方法: 在某一公共文件夹pub下创建mixin文件夹,其下创建mixinTest.js const mixinTest = { created() { console.log(`components

  • 详解Vue的组件中data选项为什么必须是函数

    官方解释 data 必须是函数 构造 Vue 实例时传入的各种选项大多数都可以在组件里使用.只有一个例外:data 必须是函数.实际上,如果你这么做: Vue.component('my-component', { template: '<span>{{ message }}</span>', data: { message: 'hello' } }) 那么 Vue 会停止运行,并在控制台发出警告,告诉你在组件实例中 data 必须是一个函数.但理解这种规则为何存在也是很有益处的,

  • MongoDB中的push操作详解(将文档插入到数组)

    目录 1. 概述 2. 数据库初始化 3. 使用 Mongo Query 进行推送操作 4. 使用Java驱动代码进行推送操作 4.1. 使用 DBObject 4.2. 使用 BSON 文档 5. 使用 addToSet操作符 5.1. 使用addToSet运算符的 Shell 查询 5.2. 使用addToSet运算符的 Java 驱动程序 6. 结论 总结 1. 概述 在本教程中,我们将介绍如何在MongoDB中将文档插入到数组中.此外,我们将看到 $push 和 $addToset 运算

  • 详解vue 2.6 中 slot 的新用法

    最近发布不久的Vue 2.6,使用插槽的语法变得更加简洁. 对插槽的这种改变让我对发现插槽的潜在功能感兴趣,以便为我们基于Vue的项目提供可重用性,新功能和更清晰的可读性. 真正有能力的插槽是什么? 如果你是Vue的新手,或者还没有看到2.6版的变化,请继续阅读.也许学习插槽的最佳资源是Vue自己的文档,但是我将在这里给出一个纲要. 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 插槽是什么? 插槽是Vue组件的一种机制,它允许你以一种不同于严格的父子关系的方式组合组件.插

  • 详解vue在项目中使用百度地图

    第一步,去百度地图开发者申请秘钥. 第二步在项目中引入,具体如下 其中index.html存放地图链接,代码如下 然后在APP.vue里面实现,代码如下 <template> <div id="app"> <div id="allmap" ref="allmap"></div> <router-view></router-view> </div> </tem

  • 详解Vue源码中一些util函数

    JS中很多开源库都有一个util文件夹,来存放一些常用的函数.这些套路属于那种常用但是不在ES规范中,同时又不足以单独为它发布一个npm模块.所以很多库都会单独写一个工具函数模块. 最进尝试阅读vue源码,看到很多有意思的函数,在这里分享一下. Object.prototype.toString.call(arg) 和 String(arg) 的区别? 上述两个表达式都是尝试将一个参数转化为字符串,但是还是有区别的. String(arg) 会尝试调用 arg.toString() 或者 arg

  • 详解Vue改变数组中对象的属性不重新渲染View的解决方案

    在解决问题之前,我们先来了解下 vue响应性原理: Vue最显著的一个功能是响应系统-- 模型只是一个普通对象,修改对象则会更新视图. 受到javascript的限制,Vue不能检测到对象属性的添加或删除,因为vue在初始化实列时将属性转为getter/setter,所以属性必须在data对象上才能让vue转换它. 但是vue可以使用 Vue.set(object, key, value)方法将响应属性添加到嵌套的对象上:如下代码: Vue.set(obj, '_isHover', true);

  • 详解VUE 对element-ui中的ElTableColumn扩展

    公司有一个新的需求,点击ElTableColumn的头部可以进行搜索,这个功能同事已经做出来了,但是使用有些不方便,自己就打算封装成一个组件,学习一下. ElTableColumn本来是这个样子的: 要做成的是这个样子: 我直接就放代码了,挨着挨着说明太多了. 代码的结构: 组件 <!-- ElTableColumnPro.vue --> <template> <el-table-column v-if="visible" :formatter="

  • 详解Vue的watch中的immediate与watch是什么意思

    immediate immediate设为true后,则监听的这个对象会立即输出,也就是说一刷新页面就会在控制台输出,当然此时页面上的数据我们还没来得及手动让其发生变化,所以在控制台输出的newValue为我们在代码中默认设置的值,oldValue输出为"undefined".如 当我们手动改变newValue.id的值后,输出如下: 如果不设置immediate,或者将immediate设为false的话,则刷新页面后不会立即监听此对象,也就是控制台不会有输出,必须要监听的对象有值改

  • 详解vue.js之props传递参数

    本篇文章通过demo实例给大家详细分析了props传递参数的用法以及遇到问题后的解决办法,以下是全部内容. 前段时间用vue做一个后台管理系统,其中每一页都需要一个表格来展示信息.自然就想到了将表格提取出来做成公共组件,将不同页面的数据传入进行渲染,达到复用的目的. demo地址 1. 问题发现 在父组件中,需要向表格组件传递的数据有表格的内容数据tableData,表格的页面数据page. <div> <my-table :table-data="tableData"

随机推荐