学习笔记

103 阅读5分钟

vue的高级用法

动画特效

一般来说,一说起vue动画特效,想的是transition,

  1. transition 实现路由切换动画

首先,我们有一个app.vue的文件 Home - > list -> detail 常见的动画 页面从右到左 detail - > list -> Home 反之是从左到右

第一步 先写一个home页面 list页面,detail 页面

第二步 定义路由跳转 并且定义一个路由深度(重点)

第三步 设置样式

插槽 slot

slot 是一个动态的块, 在组件模板中占好位置,当使用该组件的时候,组件里面的内容就会替换组件模板种slot的位置 一般都是 dom 上的复用。在组件中的dom复用 让用户可以更好的拓展组件,更好的复用组件和一些定制化的处理

常见的布局组件

  1. 插槽的使用

默认的slot使用

在子组件中 标签确定渲染的位置,标签里也可以放一些dom结构 当父组件使用的时候,如果没有往插槽中传入内容,slot标签内的dom结构就会显示在页面

具名slot的使用

子组件用v-slot:xxx来标识插槽的名字

父组件在使用的时候,在默认插槽的基础上加上slot属性,属性值就是xxx

父:

子: <slot name="test>

作用域slot的使用

组件之间传递数据

父:

子:

一个带slot的组件

  1. 插槽的原理

两个点, 一个是递归解析的slot,拿到所有的slot, 一个是 处理default的点,如果有名字,往拿到的带名字的slot的传入信息 如果默认没有名字,那就是defult

总结:插槽的本质是渲染dom的过程中的一个占位置的东西 他在渲染的时候会去匹配带有名字的slot, 然后在子中找到带有名字的地方去一一替换

Mixin

slot体现在dom渲染层的复用 mixin体现在逻辑层的复用

mixin本质是一个js对象, 可以包含任意一个东西, 比如 data, components, methos,生命周期, computed 等 类似于类的继承

但是mixin分为 局部混入 一般就写在单个页面的组件中

全局混入 一般写在main.js中的

1.mixin的使用

  • mixins/index.js 复用一个东西 记录浏览页面的事件
  • page-1.vue
  • page-2.vue

tips:

  • 如果生命周期钩子有复用的话,会先执行mixin的钩子,然后再执行组件的钩子
  • 当组件内存在于mixin相同的data key时, 组件内部的优先级高,会覆盖mixins里的值

2.mixin 实现原理

  • 递归处理mixins ,处理的时候他会做一个合并,因为父级和子集里里面都会有一个钩子,所以不会是覆盖,是一个合并。它可能是一个对象来存储,只不过会有一个先后顺序

  • 先遍历合并 parent ( extends 的父对象,也就是 mixins ),

  • 调用 mergeField( 就是合并各种字段 ) 方法进行合并

  • 遍历child,就是刚才用的组件,合并,补上 parent 中没有的值( 因为有的组件会有自己的key ),然后继续调用mergeField

  • 覆盖策略 分为四种

  • 替换型策略 - 同名的props, methods, inject, computed, 后者会替代前者

if(!parentVal){
    return childVal
}
const res = Object.create(null)

extend( res, parentVal ) 
// 内部会有一个extend 的方法, 将父级的值给赋值进去

if(childVal){
    extend(res,childVal)
}

return res

/**
 *   思路: 如果mixin没有这个数据,直接返回组件里的数据
 *   然后它默认用这个结果 反正最后返回的是这个结果
 *   我们创建一个干净对象,把当前mixins的数据全部赋值到这个创建的对象中,
 *   现在这个结果是mixin里面的数据, 然后再判断是否有组件里的数据的,
 *   如果组件里的数据有,再把数据里的数据覆盖到结果里面去,
 *   也就是说在后面执行的extend方法。他会覆盖前面的数据。
 *   也就是说组件里面的东西会覆盖 mixin 里面的数据。这就是替换型策略
 * 
 * /

  • 和并型策略 - data, 但是用过set方法进行合并和重新赋值的
const childData
const parentsData

if(childData){
    return mergeData(childData, parentData)
} else {
    return parentData
}
// mergeData 其实就是一个合并
function mergeData(to, from){
    if(!from){
        return to
    }
    const keys = Object.keys(from)
    for(let i = 0;i<keys.length;i++>){
        let key = keys[i]
        let toVal = to[key]
        let fromVal = from[key]
        if(!to.hasOwnProperty(key)){
            set(to, from, fromVal)
        } else if(typeof toVal === 'object'){
            mergeData(toVal,fromVal)
        }
    }
}
  • 队列型策略 -- 针对生命周期和watch 因为他们本质也是一个函数 它会做成一个数据,然后挨个执行,优先之宗mixin里面的方法

  • 叠加型策略 component directives filters

  • 通过原型链来进行叠加 比如 filter

const res = Object.create(parentVal|| null)
if(childVal){
    for(let key in childVal){
        res[key] = childVal[key]
    }
}
return res

过滤器 --- Filter --- v3 弃用,建议通过computed 来处理

不改变原始数据,对数据进行加工处理。一般用来做 格式的转换,可以理解为一个纯函数

    1. filter 的使用
  • 其实就是一个函数的执行

    1. 实现原理
  • 在编译阶段通过parseFilters 将过滤器编译成函数调用

  • 串联的过滤器是一个嵌套的函数调用,前一个过滤器的执行结果,,最后一个过滤器函数的参数


function parseFilters(filter) {
    let filters = filter.split('|')
    let expression = filters.shift.trim()
    if(filters) {
        for(let  = 0;i<filters.length;i++>) {
            expression = wrapFilter( expression, filters[i].trim() )
        }
    }
}

function wrapFilter(exp, filter){
    const i = fllter.indexof('(')
    if(i < 0 ){
        return `_f(${filter})(${exp})`
    }
}

插件 Plugin

简单来说 插件就是针对Vue的功能的增强和补充

  1. 使用 剪贴板插件

  2. 什么是插件? 如何编写一个插件

MyPlugn.install = function(Vue, options) {
    Vue.myGlobalMethod = function() {}
    Vue.directive('my-directive', {
        bind(el,binding, vnode, oldNode){}
    })
    Vue.mixin({
        // 比如全局混入
        created:function() {
            if(options.debug){
                console.log(111)
            }
        }
    })
    Vue.prototype.$copyText = function() {}
}
/*
*  为什么第一个参数vue, 因为我们是对Vue做的一些扩展,所以肯定是需要用到的
* Options 是我们自己要用到的东西 
**/
Vue.use(Mypluin, {})
  1. Vue.use 做了什么
  • 判断当前插件是否已经安装过, 防止重复安装
  • 处理参数, 调用插件的install方法,第一个参数是Vue 实例
/**
 * plugin 可能是一个函数或者一个对象
 * 
 */
Vue.use() = function(plugin) {
    // installPlugins 当前已经安装的
    if(!this._installedPlugins){
        this._installedPlugins = []
    }
    const installPlugins = this._installedPlugins

    if(installPlugins.indexOf(plugin).length > -1){
        return this
    }
    
    const args = Array.from(arguments)
    args.unshift(this) // this === Vue

    if(typeof plugin.install === 'function'){
        plugin.install.apply(plugin, args)
    } else if(typeof plugin === 'function'){
        plugin.apply(null,args)
    }

    installedPlugins.push(plugin)

    return this
}
    

常见组件库介绍

vant iview element-ui ant-design-vue vue-material

  1. 按需引入, 方便的按需引入
  2. 组件的设计规范, 调研下公司的其他团队有什么样的组件需求
  3. 高度可扩展
  4. 版本迭代 break, changlog