# 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
← vue-router keepAlive →