Vue进阶构造属性

Vue构造属性: directives、mixins、extends、provide、inject

1.Directives 指令

2种写法
1' 声明一个全局指令

Vue.directive('x',directiveOptions)

[图片上传失败...(image-85a3-1649369122915)]

例子:造出v-x,点击即打印x。
声明指令x,当元素被插入到页面中之后,我们就监听它的click事件。

1.先声明
main.js
Vue.directive('x',{ //单个directive
  inserted:function(el){
    el.addEventListener('click',()=>{console.log('x')})
  },
})

2.再使用x指令
进入App.vue组件

你可以在任何组件里用v-x了。
inserted你把el放哪个元素上,el就是哪个元素,比如放上,el就是

2' 声明一个局部指令
v-x只能在该实例中用

new Vue({
 ...,
 directives:{
   "x":directiveOptions
 }
})

例子: 只能在HelloWord.vue组件里用 x

HelloWord.vue


directiveOptions的其它属性

常用的钩子函数:bind、inserted、unbind

文档: 钩子函数、钩子函数参数
[图片上传失败...(image-59a3ff-1649369122915)]

函数接收的参数,都是Vue传给我们的:el、info、vnode、oldVnode
1.el 就是你把v-x绑到哪个元素上去了
2.info 就是除了传元素外,你还传了哪些东西。info包含了很多详细的消息,基本上你要的东西都在第2个参数里。

原文是binding对象:
[图片上传失败...(image-47e806-1649369122915)]

3.vnode 元素对应的虚拟节点
4.oldVnode 之前的虚拟节点,有可能这个元素是从旧到新

例子: 模仿v-on,自制v-on2指令

new Vue({
  directives: {
    on2: {
      inserted(el, info) {
        //console.log(el); 打印出
        //console.log(info); 打印出一个对象
        console.log(info.arg);
        el.addEventListener(info.arg, info.value);
      },
      unbind(el, info) { //unbind用于清理垃圾,删除监听
        el.removeEventListener(info.arg, info.value);
      }
    }
  },
  template: `
    
  `,
  methods: {
    hi() {
      console.log("hi");
    }
  }
}).$mount("#app");

addEventListener时无法确定是否是click,因为还有可能是其它事件,比如keyup。此时可以利用第2个参数拿到用户传的事件。用info得到用户传的事件

info拿到的是个对象
[图片上传失败...(image-10a298-1649369122915)]

当元素被插入到页面中时,我们就监听这个元素的事件和对应的方法。

函数简写不推荐

指令的作用
1.主要用于DOM操作
Vue实例/组件用于数据绑定、事件监听、DOM更新
Vue指令主要目的就是原生DOM操作
2.减少重复
如果某个DOM操作你经常使用,就可以封装为指令
如果某个DOM操作比较复杂,也可以封装为指令

解析
1.主要用于DOM操作
平时在用Vue时从来不做DOM操作,只是改数据,数据自动更新UI。但是我们在实际开发中有时不得不写DOM操作,这时可以把DOM操作封装成一个指令,然后只传个函数给这个指令这样就可以永远不去接触DOM操作了。

new Vue({})一般会传data、methods、钩子函数主要用途就是数据绑定、事件监听、DOM更新。DOM更新不是通过DOM API更新,而是直接通过监听器去更新。如果你要进行DOM操作,就只能用Vue指令,Vue组件和Vue指令各司其职。

mixins 混入

mixins目的也是为了减少重复,就是把一些属性复制到你的组件上。
类比
1.directives的作用是减少DOM操作的重复
2.mixins的作用是减少data、methods、钩子的重复,也就是减少构造函数的重复。

示例
使用mixins减少重复

App.vue



Child1.vue



Child2.vue


Child3.vue、Child4.vue、Child5.vue代码略...

log.js
const log = { //log必须是对象
  data() { //2个data会智能合并
    return {
      name: undefined,
      time: undefined
    };
  },
  created() {
    if (!this.name) { 
      throw new Error("need name");
    }
    this.time = new Date();
    console.log(`${this.name}出生了`);
  },
  beforeDestroy() {
    const now = new Date();
    console.log(`${this.name}死亡了,共生存了 ${now - this.time} ms`);
  }
};
export default log;

mixins的实现思路

五个组件都有构造函数data、created、beforeDestroy,那我们就把公共的抽到一个地方。

步骤
1.新建目录mixins、新建文件log.js,然后将共有的剪切到log.js里。
log.js代码参照上面
2.使用log
Child1.vue代码参考上面


mixins技巧
选项智能合并文档
也可以使用全局Vue.mixin 但不推荐使用

extends 继承、扩展

extends也是构造选项里的一个选项,跟mixins很像,也是复制减少重复但形式不同。extends更抽象高级,但还是推荐用mixins

步骤
1.新建文件MyVue.js,这不是Vue组件。

import Vue from "vue"
const MyVue = Vue.extend({ //继承Vue,MyVue就是Vue的一个扩展
  data(){ return {name:'',time:undefined} },
  created(){
    if(!this.name){console.error('no name!')}
    this.time = new Date()
  },
  beforeDestroy(){
    const duration = (new Date()) - this.time
    console.log(`${this.name} ${duration}`)
  },
  //mixins:[log] 也可以使用mixins
})
export default MyVue

2.导入+继承

Child1.vue


extends是比mixins更抽象一点的封装。如果你嫌写5次mixins麻烦,可以考虑extends一次,不过实际工作中用的很少。

provide(提供) 和 inject(注入)

例子

App.vue



流程
1.新建ChangeThemeButton组件:新建ChangeThemeButton.vue

ChangeThemeButton.vue



Child1.vue


2.App.vue完善需求实现切肤
代码参考上面App.vue

3.provide + inject
App组件(App.vue)只要切换自己的“data的themeName值”就能换肤,那如何在按钮里(ChangeThemeButton组件)改变App的data?自己只能改变自己的data,怎么才能改变别人的data?用provide实现改变别人的data。

(1)provide:在提供数据的地方写provide,提供给别人改

App.vue

注意:provide提供的是字符串的复制品,拿到的是string,不能改,应该把改的函数传过来,拿到函数的引用调用它就行(changeTheme)。

App.vue
provide() {
    return {
      themeName: this.themeName,//提供给别人用或改
      changeTheme: this.changeTheme,//提供给别人用或改
    };
  },
methods: {
    changeTheme() {
      if (this.themeName === "blue") {
        this.themeName = "red";
      } else {
        this.themeName = "blue";
      }
    },
    
ChangeThemeButton.vue
  
    

字符串拿来时已经复制了,改复制品没用,也可以用对象的引用,但不推荐。因为当这样做的人多了之后就没法控制量了,变量被到处改,无法知道变量处于什么状态,容易失控。

知识点
1.:class=""双引号是XML的双引号,不是JS的双引号。
``这是JS的引号

解析:第1个class是app。第2个class是theme-${themeName},bule和red存在themeName里。 第3个class是fontSize-${fontSizeName}

2.CSS选择器

同时设置多个class .app.theme-blue{ background:blue } //如果一个元素同时满足这2个选择器,一个class为app,一个class为theme-blue,那么就设置为blue .app.theme-blue button{ background:blue } //如果一个元素能同时满足app和theme-blue,那么它里面的button就是蓝色 .app .theme-blue //如果app里面有theme-blue

你可能感兴趣的:(Vue进阶构造属性)