您的位置:首页 > Web前端 > Vue.js

前端修仙路- vue基础进阶

2020-06-04 05:23 405 查看

前端修仙路- vue基础进阶

前言:我们大多数人在使用vue的时候,觉得很简单,但实际基础不扎实,有很多好用的特性项目中并没有用到,久而久之就忘了,特写此文铭记。

混入(mixin)

概念解释: 当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

混入规则

  1. data混入: 合并data,如果键名冲突以组件数据优先。
  2. 钩子混入(生命周期函数): 同名钩子合并成一个数组,依次调用,并且混入钩子优先调用。
  3. 值为对象的混入:如 methods、components 和 directives,将被合并为同一个对象。键名冲突时,组件数据优先。

eg:

var mixin = {
created: function () {
console.log('混入对象的钩子被调用')
},
data: function () {       //混入data
return {
message: 'hello',
foo: 'abc'
}
}
}

new Vue({
mixins: [mixin],          //局部混入
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
}
})
//=> 混入对象的钩子被调用
// => { message: "goodbye", foo: "abc", bar: "def" }

全局混入

// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})

new Vue({
myOption: 'hello!'
})
// => "hello!"

小提示

请谨慎使用全局混入,因为它会影响每个单独创建的 Vue 实例 (包括第三方组件)。

大多数情况下,只应当应用于自定义选项
,就像上面示例一样。推荐将其作为插件发布,以避免重复应用混入。

自定义指令(directive)

概念解释: 常见的指令有v-model,v-show等,当你需要操作dom的时候,就可以用自定义指令来处理。

钩子(指令生命周期)

  • bind:
    只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:
    被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:
    所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
  • componentUpdated:
    指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:
    只调用一次,指令与元素解绑时调用。

钩子参数

含有黄色标注的应该重点记忆,比较常用:

  • el:指令所绑定的元素,可以用来直接操作 DOM。
  • binding:
    一个对象,包含以下 property:
    name:
    指令名,不包括 v- 前缀。
  • value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
  • oldValue:
    指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  • expression:
    字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
  • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
  • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
  • vnode:
    Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
  • oldVnode:
    上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
  • eg:

    // 注册全局指令 `v-focus`
    Vue.directive('focus', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted: function (el,binding) {
    // 聚焦元素
    el.focus()
    }
    })
    
    //注册局部指令
    export default{
    // ...省略组件无关选项
    directives: {
    focus: {
    // 指令的定义
    inserted: function (el,binding) {
    el.focus()
    }
    }
    }
    }
    // <input v-focus>  使用指令

    动态指令参数

    指令的参数可以是动态的。例如,在

    v-mydirective:[argument]="value"
    中,argument 参数可以根据组件实例数据进行更新!

    // 注册v-pin指令
    Vue.directive('pin', function (el, binding) { //为函数表示触发bind和update
    el.style.position = 'fixed'
    var s = (binding.arg == 'left' ? 'left' : 'top')
    el.style[s] = binding.value + 'px'
    }
    )
    
    new Vue({
    el: '#dynamicexample',
    data: function () {
    return {
    direction: 'left'
    }
    }
    })
    
    // <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>

    过滤器(filter)

    用途:过滤器常用于一些常见的文本格式化。

    两种注册方式:

    // 全局注册capitalize过滤器
    Vue.filter('capitalize', function (value) {
    if (!value) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
    })
    
    // 局部注册
    export default{
    // ...省略无关选项
    filters: {
    capitalize: function (value) {
    if (!value) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
    }
    }
    }

    使用方式也有两种:

    <!-- 在双花括号中 -->
    {{ message | capitalize }}
    
    <!-- 在 `v-bind` 中 -->
    <div v-bind:message="message | capitalize"></div>

    插件

    概念解释:插件通常用来为 Vue 添加全局功能。

    用途

    1. 添加全局方法或者 property
    2. 添加全局资源:指令/过滤器/过渡等
    3. 通过全局混入来添加一些组件选项,如
      vue-router
    4. 添加 Vue 实例方法,通过把它们添加到
      Vue.prototype
      上实现

    自定义插件:

    let MyPlugin = {};
    MyPlugin.install = function (Vue, options) {
    // 1. 添加全局方法或 property
    Vue.myGlobalMethod = function () {
    // 逻辑...
    }
    
    // 2. 添加全局资源
    Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
    // 逻辑...
    }
    ...
    })
    
    // 3. 注入组件选项
    Vue.mixin({
    created: function () {
    // 逻辑...
    }
    ...
    })
    
    // 4. 添加实例方法
    Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
    }
    }
    export default MyPlugin

    使用插件:

    // 调用 `MyPlugin.install(Vue)`
    Vue.use(MyPlugin, { someOption: true }) //第二个参数可选

    函数式组件(functional)

    概念解释:函数式组件用来定义那些没有响应数据,也不需要有任何生命周期的场景,它只接受一些props 来显示组件。

    使用方法:

    • 方式一:
    Vue.component('component', {
    functional: true,
    // Props 是可选的
    props: {
    // ...
    },
    // 为了弥补缺少的实例
    // 提供第二个参数作为上下文
    render: function (createElement, context) {
    // ...
    }
    })
    • 方式二
    <template functional>   //render 可以改写成template
    <div class="root">
    hello {{props.name}}  //渲染props
    </div>
    </template>
    
    <script>
    export default {
    functional:true,    //启用函数式组件
    props:{
    name:{
    type:String,
    default:'hzz'
    }
    },
    name:'HelloWorld'
    }
    </script>

    正因为函数组件没有响应式数据,也不需要生命周期函数,因此性能会有所提升,如果只是纯静态展示内容,推荐使用函数式组件。

    提供/注入(provide/inject)

    概念解释:这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的Context特性很相似。

    用途:provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

    eg:

    // 祖先组件
    export default{
    //...省略组件无关选项
    provide: {
    foo: 'bar'
    }
    }
    
    // 子孙组件
    export default{
    //...省略组件无关选项
    inject: ['foo'],
    created () {
    console.log(this.foo) // => "bar"
    }
    }

    提示

    provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

    彩蛋

    看vue文档,发现了一个奇特的跨组件传值方式,特分享给大家:

    共享数据

    import Vue from 'vue'
    const state = Vue.observable({count:0})
    export default state

    组件A

    <template>
    <div class="root">
    crossA count: {{this.count}}
    </div>
    </template>
    
    <script>
    import state from '../module/crossState';
    export default {
    props:{},
    computed:{
    count(){return state.count}
    },
    name:'CrossA'
    }
    </script>

    组件B

    <template>
    <div @click="changeCount()" class="root">
    crossB count: {{this.count}}
    </div>
    </template>
    
    <script>
    import state from '../module/crossState';
    export default {
    props:{},
    methods:{
    changeCount(){
    state.count++
    }
    },
    computed:{
    count(){return state.count}
    },
    name:'CrossB'
    }
    </script>

    当点击组件B的时候,组件A的值也会跟着改变,其核心利用了

    Vue.observable
    定义了一个响应式对象,而计算属性依赖该对象属性,于是count改变时,重新计算属性,实现了数据的双向绑定,也实现了跨组件传值。

    这期到此结束 😃

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: