# vue进阶

# vue组件

全局组件可以使用Vue.component在mainjs中定义,也可以使用vue文件然后引入

import Vue from 'vue'
import Quanju from "./components/Quanju.vue"
Vue.component('Quanju',Quanju)//组件名+组件

然后在需要使用的地方直接<Quanju/>而不需要引用

# vueextend

使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

  • 扩展组件功能运用
  • 创建一个新功能,不需要父子组件传值写的那么复杂
  • 场景:自定义弹窗
<template>
  <div class="about" >
	<div>
		<!--formatTime是全局定义的过滤器-->
		<div>{{time|formatTime}}</div>
	</div>
  </div>
</template>
<script>
	import Vue from 'vue'
	import Quanju from "@/components/Quanju.vue"
	export default{
		data(){
			return{
				time:new Date(),
				settimer:null,
			}
		},
		mounted(){
			var tem=Vue.extend(Quanju)
			let go =new tem({
				el:document.createElement('div'),
				data(){
					return{
						num:1,					
					}
				},
				mounted(){
					this.num++;
					console.log(188888+this.num);
					console.log(this.$service.telNumberCheck(13398485645))			
				}
			});
			var s=document.getElementById("about")
			console.log(s)
			s.appendChild(go.$el)
			this.settimer=setInterval(()=>{
				this.time=new Date()
				console.log(1)
			},1000)
		},
			
		beforeDestroy(){
			clearInterval(this.settimer)
		},
	} 	
</script>

------------------------------------弹框制造----------------------------------------

  • Toast.vue
 <template>
 	<div class="toast"  v-if="isShow">
 		<div class="toast-div">{{ text }}</div>		
 	</div>
 </template>
  
 <script>
 export default{	
 	data(){
 		return {
 			text:'内容',
 			isShow:true,
 			duration:1500
 		}
 	},
	methods:{
		
	}
 }
 </script>
  
 <style>
 *{
 	margin: 0;
 	padding: 0;
 }
 .toast{
    position: fixed;
    left: 50%;
    transform: translate(-50%, 0);
    margin-top: 5rem;
    background: #61aedc;
    line-height: 0.7rem;
 	color: #FFFFFF;
 	padding:  1.5rem;
 	border-radius: 0.2rem;
 }
 </style>
  • toast.js
import Vue from 'vue'; 
import Toast from '@/components/Toast';     //引入组件
let ToastConstructor  = Vue.extend(Toast) // 返回一个“扩展实例构造器”
 
let myToast = (text,duration)=>{
	let toastDom = new ToastConstructor({
		el:document.createElement('div')    //将toast组件挂载到新创建的div上
	})
	document.body.appendChild( toastDom.$el )   //把toast组件的dom添加到body里
	
    toastDom.text = text;
    toastDom.duration = duration;
 
    // 在指定 duration 之后让 toast消失
    setTimeout(()=>{
        toastDom.isShow = false;  
    }, toastDom.duration);
}
export default myToast;
<template>
  <div class="hello">
	<button @click="showToast">按钮</button>
  </div>
</template>

<script>
import Vue from 'vue';
import toast from '../js/toast.js';        
Vue.prototype.$toast = toast;       //给Vue对象添加$toast方法
export default {
  methods:{
	showToast(){
			this.$toast('999',2000);             
		}	
  }
}
</script>

# extends

组件选项 extends(可理解为单继承,只接受一个extends),可以使用extends引用对象的方法。使用场景极少!

//Parents.js
export default{
		created() {
			console.log("父组件")
		},
		mounted(){
			console.log("action")
		},
		methods:{
			btn(){
				console.log("--------")
			}
		}
	}
<template>
	<div >display		
	   <div  @click="btn"></div>
	</div>
</template>
<script>
	import parent from "@/components/Parents"
	export default{
		extends:parent	
	}
</script>

# mixin

混合,可以提取混合内容中的方法和data,生命周期等,mixins是数组,可以多个

  • 组件 data, methods,computed等 优先级高于 mixin data, methods,computed... 优先级

  • 生命周期函数,先执行 mixin 里面的,再执行组件里面的

  • 自定义的属性,组件种的属性优先级高于 mixin 属性的优先级

  • 替换型:props inject methods computed 重复的会被替换

  • 合并型:data 类似Object.assign(mixins.data,this.data)

  • 队列型:watch 生命周期=>合并成一个数组,依次执行

如果没有样式,可以直接js文件

/*
*<template>
	<div>{{qq}}</div>
</template>
<script>*/
	export default{
		data(){
			return {
				qq:"9x72x03xx"
			}
		},
		methods:{
			hunhe(){
				console.log("混合")
			}
		}
	}
/*
*</script>
*<style>
	div{
		color:red		
	}
</style>*/
<template>
  <div class="about" >
	<div @click="hunhe">mixin-{{qq}}</div>
  </div>
</template>
<script>
	import mixin from "@/components/Mixin"
	export default{
		mixins: [mixin]
	} 	
</script>
  • 也可以使用全局mixin,这样就不需要在每个用到的子组件中注入mixins:[xxx]这样的代码,但是维护性不高。
// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

new Vue({
  myOption: 'hello!'
})
// => "hello!"
  • 修改自定义属性在mixins和vue组件的优先级
  • 自定义属性,不在data中,是直接在vue实例上,可用option读取 => this.$options.number
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 28</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const myMixin = {
    number: 1
  }

  const app = Vue.createApp({
    mixins: [myMixin],
    number: 2,
    template: `
      <div>
        <div>{{this.$options.number}}</div>
      </div>
    `
  });
  app.config.optionMergeStrategies.number = (mixinVal, appValue) => {
    return mixinVal || appValue;
  }

  const vm = app.mount('#root');
</script>
</html>

# vue插件开发 Vue.use() install

export default {
    install: function (Vue, options) {
        // 1. 添加全局方法或属性
	   Vue.prototype.test =function (){
		  console.log('ko')
		  return true
		}
        // 2. 添加全局资源
        Vue.filter('formatTime', function (value) {
           return 'xxx'
        })

        //  添加注入组件时,是否利用console.log来通知的判断条件,也是组件实例属性
        Vue.prototype.NOTICE = true;

		let a=100;
        // 3. 注入组件
        //  注入组件,插件加载开始前提示
        Vue.mixin({
            created: function () {
                if (this.NOTICE)
                    console.log("组件开始加载")
            },
			mounted(){
				console.log("挂载");
				console.log(document.getElementById("T1"))
			},
            methods: {
                test: function () {
                    console.log("mixin test");
                }
            }
        })

        // 4. 添加实例方法
        //  服务组,将实例方法整合到$service中,避免命名冲突
        Vue.prototype.$service = {
            //电话号码合法性检查
            telNumberCheck: function (tel) {
                var pattern = /(^(([0\+]\d{2,3}-)?(0\d{2,3})-)(\d{7,8})(-(\d{3,}))?$)|(^0{0,1}1[3|4|5|6|7|8|9][0-9]{9}$)/;
                return pattern.test(tel)
            }
        }
    },
	}
//main.js
import Vue from 'vue'
import App from './App.vue'

import eg from "./js/plugin.js"
Vue.use(eg)

new Vue({
  render: h => h(App)
}).$mount('#app')

# vue3定义使用插件

  • app.config.globalProperties.$sayHello 添加vue的全局属性,使用$定义,在vue中可以直接this.$xxx获取到
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 32</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  // plugin 插件, 也是把通用性的功能封装起来
  const myPlugin = {
	 //app:Vue options:传递的参数
    install(app, options) {
      app.provide('name', 'Dell Lee');
      app.directive('focus', {
        mounted(el) {
          el.focus();
        }
      })
      app.mixin({
        mounted(){
          console.log('mixin')
        }
      })
      app.config.globalProperties.$sayHello = 'hello world';
    }
  }

  const app = Vue.createApp({
    template: `
      <my-title />
    `
  });

  app.component('my-title', {
    inject: ['name'],
    mounted() {
      console.log(this.$sayHello);
    },
    template: `<div>{{name}}<input v-focus /></div>`
  })

  app.use(myPlugin, { name: 'dell'});

  const vm = app.mount('#root');
</script>
</html>

# vue3插件和mixins集合

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 33</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  // 对数据做校验的插件
  const app = Vue.createApp({
    data() {
      return { name: 'dell', age: 23}
    },
    rules: {
      age: {
        validate: age => age > 25,
        message: 'too young, to simple'
      },
      name: {
        validate: name => name.length >= 4,
        message: 'name too short'
      }
    },
    template: `
      <div>name:{{name}}, age:{{age}}</div>
    `
  });
  //本例中,不适用插件直接使用app.mixin即可,使用了插件更好明白功能(需要注册插件,插件名比较明显)
  const validatorPlugin = (app, options) => {
    app.mixin({
      created() {
        for(let key in this.$options.rules) {
			
		  console.log(this.$options)
          const item = this.$options.rules[key];
          this.$watch(key, (value) => {
            const result = item.validate(value);
            if(!result) console.log(item.message);
          })
        }
      }
    })
  }

  app.use(validatorPlugin);
  const vm = app.mount('#root');
</script>
</html>

# vue keycodes

类型:{ [key: string]: number | Array<number> }

默认值:{}

//用法:
Vue.config.keyCodes = {
  v: 86,
  f1: 112,
  // camelCase 不可用
  mediaPlayPause: 179,
  // 取而代之的是 kebab-case 且用双引号括起来
  "media-play-pause": 179,
  up: [38, 87]
}
<input type="text" @keyup.media-play-pause="method">

# nextTick

nextTick

最后更新: 4/22/2024, 7:43:33 AM