Vue音乐播放器学习笔记(5) - mixin混合 + ( vm.$options ) + ( Vue.extend( options ) ) + ( Vue.directive全局自定义指令 和 directives局部自定义指令 ) + ( 动态组件 和 is属性 )

[一] Vue mixins(混合)

(一) 不同组件引用mixin

mixin.js       



export const mixinUse = {
  data() {
    return {
      show: false
    }
  },
  created() {
    this.go()
  },
  methods: {
    go() {
      this.show = !this.show
    }
  },
  mounted() {
    console.log('这是mixin中的mounted()钩子函数,先执行')
  }
}
-----------------------------------------------------------------------------------
hellowWorld.vue    主页面,引用 modelA组件 和 mixin.js




<template>
  <div>
    这是主页面
    <modelA v-show="show"></modelA>
    <div @click="go">点击显示</div>
  </div>
</template>

<script>
  import ModelA from 'components/modela/modela.vue'
  import {mixinUse} from '@/mixin.js'

  export default {
    mixins: [mixinUse],
    components: {
      ModelA
    },
    mounted() {
      console.log('这是主页面的mounted()钩子函数,后执行')
    }
  }
</script>-----------------------------------------------------------------------------------
modelA组件       引用 modelB组件 和 mixin.js




<template>
  <div class="modelA">
    这是model A的内容AAAAAAAAAAA
    <modelB v-show="!show"></modelB>
    <div @click="go" style="margin-top: 20px">点击-显示model'B</div>
  </div>
</template>


<script type="text/ecmascript-6">
  import ModelB from 'components/modelb/modelb.vue'
  import {mixinUse} from '@/mixin.js'

  export default {
    mixins: [mixinUse],
    components: {
      ModelB
    }
  }
</script>



 

(1) 合并 (组件和mixin中相同生命周期钩子函数的执行顺序)

  • 当我们在组件上应用Mixin的时候,有可能组件与Mixin中都定义了相同的生命周期钩子,这时候钩子的执行顺序的问题凸显了出来。默认Mixin上会首先被注册,组件上的接着注册,这样我们就可以在组件中按需要重写Mixin中的语句。组件拥有最终发言权。

(2) 冲突 (组件和mixin中都有同名的method方法时,mixin中的方法被重写)

//mixin


const hi = {
  methods: {
    sayHello: function() {
      console.log('hello from mixin!')
    }
  },
  mounted() {
    this.sayHello()
  }
}

-----------------------------------------------------------------------------
//vue instance or component



new Vue({
  el: '#app',
  mixins: [hi],
  methods: {
    sayHello: function() {
      console.log('hello from Vue instance!')
    }
  },
  mounted() {
    this.sayHello()
  }
})
 
// Output in console
> hello from Vue instance!
> hello from Vue instance!

你可能已经注意到这有两个console.log而不是一个——

这是因为第一个函数被调用时,没有被销毁,它只是被重写了。我们在这里调用了两次sayHello()函数。


(二) 全局mixin(使用Vue.mixin({xxx})方法)

  • 全局Mixin被注册到了每个单一组件上。因此,它们的使用场景极其有限并且在使用的时候我们需要非常小心。一个我能想到的用途就是类似于插件,你需要赋予它访问所有东西的权限。但即使在这种情况下,我也对你正在做事情的充满警惕,尤其当你打算为应用增加通能的时候,这样做可能对你来说是个潘多拉的盒子。

Vue.mixin({
  mounted() {
    console.log('hello from mixin!')
  }
})
 
new Vue({
  ...
})

(1) 合并 (全局mixin与组件内mixin 中的生命周期钩子函数的执行顺序)

  • 每次创建组件时,全局mixin都会添加到组件实例中,如果全局mixin和组件内mixin有同名的钩子函数,钩子函数都会执行,并且先执行先执行全局后执行组件内。

(2) 冲突 (全局mixin与组件内mixin 中的非钩子函数冲突时,全局mixin被重写)

  • 对于非钩子函数,组件实例的对象属性,组件内的会覆盖全局的。

(3) 实现全局mixin的钩子函数在指定组件中执行/不执行

  • 在时机使用过程中,如果希望钩子函数中的代码只在指定的组件中执行,可以使用组件自定义options来实现( vm.$options )
main.js中的全局mixin 


Vue.mixin({
  created() {
    if (this.$options['isMixin']) {    // 如果组件中存在isMixin的自定义选项,就往下执行
      console.log('如果组件isMixin选项存在就输出这段文字')
    }
  }
})

---------------------------------------------------------------------------
helloWorld.vue组件


  export default {
    isMixin:{
      a:true   // 这里可以随便写,只要ismixin存在即可
    },
    created() {
      console.log('组件中的console.log')
    },
    mounted() {
      console.log('这是主页面的mounted()生命周期钩子函数,后执行')
    }
  }
</script>


输出结果:
main.js?1c90:19如果组件isMixin选项存在就输出这段文字
HelloWorld.vue?3c12:24组件中的console.log
HelloWorld.vue?3c12:27这是主页面的mounted()生命周期钩子函数,后执行

总结:Vue混合策略

vue ( mixin ) 和 组件 有相同的生命周期钩子函数时候,执行顺序是:先执行mixin再组件

vue ( mixin ) 和 组件 有相同非钩子函数时候,执行组件中的非钩子函数,mixin都被重写

对于钩子函数,会添加到一个函数数组里,执行顺序从前到后

对于组件的对象属性(methods等),后面的会覆盖前面的

最好不要用全局mixin


[二] vm.$options

  • 类型:Object
  • 详细:用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处


new Vue({
  customOption: 'foo',      // customOption是实例的初始化选项
  created: function () {
    console.log(this.$options.customOption) // => 'foo'
  }
})

----------------------------------------------------------------------------------------

new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: {App},
  author: {
    name: 'wu',
    age: '27'
  },
  created() {
    console.log(this.$options.author, 'this.$options')  
         // => Object {name: "wu", age: "27"} "this.$options"
  }
})


[三] Vue.extend( options )

参数:
{Object} options
用法:
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。它的目的是创建一个Vue的子类并且返回相应的 constructor。
data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数

[四] Vue.directive 自定义指令

(1)钩子函数

指令定义函数提供了几个钩子函数 (可选):

  • bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
  • inserted:被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
  • componentUpdated:所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
  • unbind:只调用一次,指令与元素解绑时调用。

(2)钩子函数参数

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



// 注册一个全局自定义指令 v-focus,作用:获取焦点

Vue.directive('focus', {

    // inserted钩子函数,作用:当绑定元素插入到 DOM 中
    // 钩子函数参数: el绑定的元素,binding对象(包含name,value,arg等)

  inserted: function (el, binding) {  
    // 聚焦元素
    el.focus()
  }
})


使用: <input v-focus>


 // inserted钩子函数:被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于document 中)。


-----------------------------------------------------------------------

/*简单模式*/
Vue.directive('minLength',function(){
  /*在bind和update阶段触发*/
})


局部自定义指令:组件中接受一个 directives 的选项: (注意:这里是directives,是复数)
改变字体颜色


directives: {
  focus: {
    // 指令的定义---
    inserted: function (el, binding) {}
  }
}
--------------------------------------------------------------------------------------


  export default {
    directives: {   // 局部自定义指令,注意有s
      color: {    // v-name
        inserted: function(el, binding) {  // inserted钩子函数,绑定元素插入DOM中时生效
          el.style = 'color:' + binding.value    // el指令绑定的元素,binding对象,有value等属性
        }
      }
    },
    data() {
      return {
        model: '',
        showOrHide: true,
        color: 'red'
      }
    },
//    mixins: [mixinUse],
    components: {
      ModelA
    },
    isMixin: {
      a: true
    },
    created() {
      console.log('组件中的console.log')
    },
    mounted() {
      console.log('这是主页面的mounted()生命周期钩子函数,后执行')
    },
    methods: {
      xianShi() {
        this.showOrHide = !this.showOrHide
      }
    }
  }




使用: <div v-color="color">v-color指令,绑定元素内的颜色</div>

           data() {
             return {
               color: 'red'
            }


(3)注意:当使用路由并且使用keep-alive的时候,自定义指令(v-focus)在inserted等钩子函数中使用获得焦点的函数将失效,因为keep-alive会保存状态,没有重新加载,即el绑定的元素已经插入dom中,所以inserted失效,这时要使用keep-alive对应的生命周期钩子函数( activated ) ,keep-alive 组件激活时调用。( deactivated 停用时调用 )


   activated() {
      this.$refs.input2.focus()
    }

[5] 动态组件 和 is属性

  • 通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,我们让多个组件可以使用同一个挂载点,并动态切换:
  • is属性 : 用于动态组件且基于 DOM 内模板的限制来工作。
tab切换


<template>
  <div class="table">
    <div>这是tab组件页面</div>
    <div>
      <div @click="go('Tab1')">选项一</div>
      <div @click="go('Tab2')">选项二</div>
    </div>
    <component :is="currentTab"></component>    // <component>元素绑定is,让组件共用一个挂载点
  </div>
</template>

<script type="text/ecmascript-6">
  import Tab1 from './tab1.vue'
  import Tab2 from './tab2.vue'
  export default {
    data() {
      return {
        currentTab: 'Tab1'
      }
    },
    components: {
      Tab1,
      Tab2
    },
    methods: {
      go(tab) {
        this.currentTab = tab
      }
    }
  }
</script>
效果图
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • 1.安装 可以简单地在页面引入Vue.js作为独立版本,Vue即被注册为全局变量,可以在页面使用了。 如果希望搭建...
    Awey阅读 10,982评论 4 129
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,198评论 0 6
  • 文/孤鸟差鱼 难得有人欣赏 你的乖张 别失了模样
    孤鸟差鱼阅读 164评论 6 3
  • 一 我愿与你泛舟于大海 要是海风把我们的船吹翻 我们就遨游海底 做一条欢快的鱼儿 二 我给你搬个板凳 你坐在门前,...
    暮雨清风阅读 302评论 50 16