vue基础三(混入,自定义指令,函数,JSX,自定义插件)

混入

Mixin 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
一个 mixin 对象可以包含任意组件选项。
当组件使用 mixin 对象时,所有 mixin 对象的选项将被“混合”进入该组件本身的选项。

var obj = {
    data:function(){
        return {
          name:'zhangsan'
        }
    }
}
export default {
  mixins:[obj]
}

<template>
  {{ username }}
  <button @click="getname">获取</button>
</template>
<script>
	var obj = {
	  data() {
	    return {
	      username: "zhangsan",
	    };
	  },
	  methods: {
	    getname() {
	      console.log(this.username);
	    },
	  },
	};
	export default {
	  mixins: [obj];  // 使用mixin对象,使obj对象选项被混合进入该组件
	 };
</script>

选项和并

当组件和 mixin 对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
每个 mixin 可以拥有自己的 data 函数。每个 data 函数都会被调用,并将返回结果合并。
在数据的 property 发生冲突时,会以组件自身的数据为优先

混合后对象和组件的有同名属性或方法时,组件中属性和方法会覆盖对象中的同名属性和方法;
而同名的钩子函数,为对象中的钩子函数先执行,组件中的钩子函数后执行,互不冲突

<template>
  {{ username }}
  <button @click="getname">获取</button>
</template>
<script>
var obj = {
  data() {
    return {
      username: "zhangsan",
    };
  },
  methods: {
    getname() {
      console.log(this.username);
    },
  },
  created(){
    console.log(1);
  }
};
export default {
  mixins: [obj],
  data() {
    return {
      username: "lisi", //属性和方法,实例优先
    };
  },
  methods: {
  },
  created(){
    console.log(2); //混入的钩子先执行,实例的钩子后执行
  }
};
</script>

同名钩子函数将合并为一个数组,因此都将被调用。
mixin 对象的钩子将在组件自身钩子之前调用。
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

全局mixin

Vue 应用程序全局应用 mixin, vue全局都可以使用全局的数据

main.js

//全局混入
var obj={
    data(){
        return{
            msg:'hello'
        }
    }
}
createApp(App).mixin(obj).use(store).use(router).mount('#app')

Home.vue

<template>
  {{msg}}   // 在vue全局中都可以使用全局mixin中的值
</template>
<script>
export default {
};
</script>

自定义指令

在实例的directive属性中,自定义指令,这些指令可以被该实例使用(私有自定义指令)。

如果是全局注册(在main.js中进行注册)的话,那么所有的组件都可以使用(全局自定义指令)。

私有自定义指令

directives节点与data,created和mothods同级

    <!-- 给自定义指令传变量 -->
    <h1 v-color="color"></h1>
    <!-- 给自定义指令传一个固定值,需要加单引号 -->
    <h1 v-color="'red'"></h1>

	  data() {
    return {
      color: 'blue'
    }
  },

  directives: {
    // 定义一个名为color的指令
    color: {
      // 当指令第一次被绑定到元素上时,会立即触发bind函数
      // el 表示当前指令被绑定到的DOM对象
      bind(el, binding) {
        // binding为用户通过=传递的值
        console.log(binding)
        el.style.color = binding.value
      }
    }
  }

bind函数只会被调用一次,只在指令第一次被绑定到元素上时才触发。

update函数在DOM被更新时被触发。

    <!-- 给自定义指令传变量 -->
    <h1 v-color="color"></h1>
    <!-- 点击按钮时bind函数不会被触发,颜色值不会被改变-->
    <button @click="color='green'">改变color值</button>

		  directives: {
    // 定义一个名为color的指令
    color: {
      // 当指令第一次被绑定到元素上时,会立即触发bind函数
      // el 表示当前指令被绑定到的DOM对象
      bind(el, binding) {
        // binding为用户通过=传递的值
        console.log(binding)
        el.style.color = binding.value
      },
      // 在每次DOM被更新时会触发
      updated(el, binding) {
        console.log(binding)
        el.style.color = binding.value
      }
    }
  }

函数简写:

如果在bind和update函数中书写一样的代码,可以将函数进行简写。

	  directives: {
    // 定义一个名为color的指令
    // 当bind和update函数内容一样时,将bind和update函数进行简写
    color(el, binding){
        console.log(binding)
        el.style.color = binding.value

    }
  }

全局自定义指令

main.js

// Vue.directive('color', {
//   bind(el, binding) {
//     el.style.color = binding.value
//   },
//   updated(el, binding) {
//     el.style.color = binding.value
//   }
// })
// 进行函数简写
Vue.directive('color', function(el, binding){
  el.style.color = binding.value
}
)

mounted函数只在元素第一次插入Dom时被调用,当DOM更新时mounted函数不会被触发。
updated函数会在每次DOM更新完成后被调用。

app.directive(
   'focus',{
	mounted(el){
		el.focus()
	},
	undated(el){ //每次DOM更新都会调用
		el.focus()
	}
})

如果mounted和updated函数中逻辑完全相同,则可以简写:

app.directive('focus', (el) => {
		el.focus()  //mounted和updated函数被触发时都是执行该操作
	},
})

指令创建

<template>
    <input type="text" v-focus>
</template>
<script>
export default {
  directives:{
	    focus:{
	    //当被绑定的元素插入到DOM中时,会自动触发mounted函数
	      mounted(el){  //el 当前元素
	        el.focus();  //获取焦点
	        el.style.border="1px solid red";
	        el.style.outline="none"
	      },
	    },
}
</script>

指令钩子函数参数

  • el:指令所绑定的元素,可以用来直接操作 DOM。

  • binding:一个对象,包含以下 property:

    • value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论 值是否改变都可用。
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo:
      true, bar: true }。
    • instance:指向vue实例。
  • vnode:Vue 编译生成的虚拟节点。

  • prevVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

     <template>
         <p v-color>哈哈哈</p>
         <p v-color="'yellow'">今天天气很好</p>  //绑定值
         <p v-color:fontSize="'30px'">小没哭了</p>  //设置指令值
         <p v-color:color.weight="'white'">啦啦啦</p>  //修饰符
     </template>
     <script>
     export default {		 
         color:{
             created(el,binding){
               el.style.backgroundColor="pink";
               el.style.color=binding.value; //对象的绑定值
               el.style[binding.arg]=binding.value;  //对象的参数的值
               if(binding.modifiers.weight){  //含修饰符的对象
                 el.style.fontWeight="700";
               }
             },
           }
       }
     }
     </script>
    

指令参数

v-focus:color
el.style[binding.arg] = 'red';  //给指令传递的参数赋值

动态指令参数

v-focus:[direction]
direction: 'color'    //可以动态改变指令的参数

指令值

v-focus:color=" 'blue' "
el.style[binding.arg] = binding.value;

渲染函数

渲染函数比模板更接近编译器。

在组件标签中传递一个属性值1-6,然后在子组件中分别使用h1-h6去包裹插槽的内容:

<template>
    <my-h :level="2">hello world </my-h>
</template>
<script>
import MyH from '../components/MyH.vue'
export default {
  components:{
    MyH
  }
}
</script>

render 函数 跟 template 一样都是创建 html 模板的,但是有些场景中用 template 实现起来代码冗长繁琐而且有大量重复,这时候就可以用 render 函数。

<script>
import { h,ref } from "vue";
export default {
  props: ["level"],
  setup(props, { slots, attrs, emit }) {
    return () => [
      h('h'+props.level,{},[slots.default()]),    //h函数  (标签名,{},[插槽] )
    ]; 
  },
};
</script>

h元素中还可以再创建子元素

<script>
import { h } from "vue";
export default {
  props: ["level"],
  setup(props, { slots, attrs, emit }) {
    return () => [
      h('h'+props.level,{},[slots.default()]), //h函数 
      h(
        "h" + props.level,
        {
          class: "title",
          style: [{ backgroundColor: "yellow" }],
        }, //h函数的第二个子元素
        [
            h("span", {}, slots.default()),
            h("span", {}, slots.default())
         ], //可以在h元素中创建多个子元素
      ),
    ]; 
    // return()=><h1>{slots.default()}</h1>
  },
};
</script>

setup() 函数

● setup函数是v3提供新的组件选项。
● 之前的data、声明周期、自定义函数都可以放置在内
● 在创建组件之前执行,初始化props,紧接着就调用setup函数,从生命周期钩子的视角来看,它会在beforeCreate钩子之前被调用
● 是mixins的强化版,比mixins更加灵活
● 因为setup()是在解析其它组件选项之前被调用的,所以避免使用this

ref() 函数

<template>
    <h1>{{count}}</h1>
    <button @click="change_count">点我</button>
</template>
<script>
import {ref} from 'vue'
export default {
  setup(){
    let count=ref(0);  //ref函数监听count的变化
    function change_count(){
      count.value+=1;
    }
    return {count,change_count}
  }
}
</script>

注:
● 在setup中定义的变量或方法,都必须通过return {xxx,xxx}暴露出去,外界才能使用
● ref函数仅能监听基本类型的变化,不能监听复杂类型的变化(比如对象、数组)

reactive函数

reactive函数用来检测复杂数据类型的变化

<template>
    <h1>{{obj.name}}</h1>
    <button @click="change_obj">点我</button>
</template>
<script>
import {ref,reactive} from 'vue'
export default {
  setup(){
    let obj= reactive({name:'zhangsan'}); //reactive函数封装引用数据类型
    function change_obj(){
      obj.name='lisi'
    }
    return {obj,change_obj}
  }
}
</script>

JSX

render函数虽然可以解决问题,但是代码写起来比较麻烦。
在 Vue 中使用 JSX 语法,它可以让我们回到更接近于模板的语法上。

自定义插件

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:
添加全局方法或者 property。如:vue-custom-element
添加全局资源:指令/过滤器/过渡等。如 vue-touch
通过全局混入来添加一些组件选项。如 vue-router
添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:

在src文件夹中创建utils文件夹
myplugin.js

//自定义插件
export default{
    install:(Vue,options)=>{
        //1.在插件中封装一个方法$getname
        Vue.config.globalProperties.$getname=()=>{
            console.log('xiaoming');
        }
        //2.在插件中封装一个指令 v-color
        Vue.directive('color', {
             created(el, binding, vnode, oldVnode) {
               el.style.color="red";  
             }       
        })
        //3.为插件创建一个mixin admin
        Vue.mixin({
            data(){
                return {
                    admin:'zhangsan'
                }
            }  
        })
    }
}

插件的使用
main.js

import myplugin from './utils/myplugin'
createApp(App).use(myplugin).use(store).use(router).mount('#app')

Home.vue

<template>
  <!-- <button @click="$getname" v-color>{{admin}}点击</button> -->
  <button @click="getname" v-color>{{admin}}点击</button>
</template>
<script>
export default {
  methods:{
    getname(){
      this.$getname();
    }
  },
}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值