Vue [Day5]

自定义指令

全局注册 和 局部注册

在这里插入图片描述
inserted在指令所在的元素 被插入到页面中时,触发

main.js

import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = false// 1.全局注册指令
Vue.directive('focus', {// inserted在指令所在的元素 被插入到页面中时,触发inserted(el) {// el就是指令所绑定的元素console.log(el);el.focus()}
})new Vue({render: h => h(App),
}).$mount('#app')

App.vue

<template><div class="app"><h1>自定义指令</h1><input v-focus ref="inp" type="text" /></div>
</template><script>
export default {// mounted() {//     this.$refs.inp.focus()// }// 2.局部注册指令directives: {focus: {inserted(el) {el.focus()}}}
}
</script><style>
</style>


### Day4 $nextTick改标题的光标异步问题

App.vue

<template><div class="app"><div v-if="isEdit"><input v-focus  ref="inp" v-model="editValue" type="text" /><button @click="over">ok</button><!-- 直接v-fous --></div><div v-else>{{ title }}<button @click="changeTitle">edit</button></div></div>
</template><script>
export default {data() {return {editValue: '',title: '我是title',isEdit: false}},methods: {changeTitle() { // 1.显示输入框(异步dom更新this.isEdit = true// 2.让输入框获取焦点// $nextTick等dom更新完,立刻执行函数体// this.$nextTick(() => {// this.$refs.inp.focus()// })},over() {this.title = this.editValuethis.isEdit = false}}
}
</script><style>
</style>


main.js

import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falseVue.directive('focus',{inserted(el){console.log(el);   el.focus()}
})new Vue({render: h => h(App),
}).$mount('#app')


指令的值

在这里插入图片描述


App.vue
<template><div class="app"><h1 v-color="color1">11111</h1><h1 v-color="color2">22222</h1></div>
</template><script>
export default {data() {return {color1: 'red',color2: 'pink'}},directives: {color: {// 1.inserted提供的是元素被添加到页面中时的逻辑inserted(el, binding) {// binding.value就是指令的值el.style.color = binding.value},// 2.update 指令的值修改的时候触发,提供值变化后,dom更新的逻辑update(el, binding) {el.style.color = binding.value}}}
}
</script><style>
</style>


小结

binding.value,可以拿到指令的值
在这里插入图片描述


v-loading 指令封装

在这里插入图片描述


在这里插入图片描述

App.vue

<template><div class="main"><div class="box" v-loading="isLoading"><ul><li v-for="item in list" :key="item.id" class="news"><div class="left"><div class="title">{{ item.title }}</div><div class="info"><span>{{ item.source }}</span><span>{{ item.time }}</span></div></div><div class="right"><img :src="item.img" alt="" /></div></li></ul></div></div>
</template><script>
// 安装axios =>  yarn add axios
import axios from 'axios'// 接口地址:http://hmajax.itheima.net/api/news
// 请求方式:get
export default {data() {return {list: [],isLoading: true}},async created() {// 1. 发送请求获取数据const res = await axios.get('http://hmajax.itheima.net/api/news')setTimeout(() => {// 2. 更新到 list 中this.list = res.data.datathis.isLoading = falseconsole.log('111')}, 2000)console.log('22222')},directives: {loading: {inserted(el, binding) {// if (binding.value == true) {//     el.classList.add('loading')// } else {//     el.classList.remove('loading')// }// 用三元写binding.value? el.classList.add('loading'): el.classList.remove('loading')},update(el, binding) {binding.value? el.classList.add('loading'): el.classList.remove('loading')}}}
}
</script><style>
/* 伪类 - 蒙层效果 */
.loading:before {content: '';position: absolute;left: 0;top: 0;width: 100%;height: 100%;background: #fff url('../public/loading.gif') no-repeat center;
}/* .box2 {width: 400px;height: 400px;border: 2px solid #000;position: relative;} */.box {width: 800px;min-height: 500px;border: 3px solid orange;border-radius: 5px;position: relative;
}
.news {display: flex;height: 120px;width: 600px;margin: 0 auto;padding: 20px 0;cursor: pointer;
}
.news .left {flex: 1;display: flex;flex-direction: column;justify-content: space-between;padding-right: 10px;
}
.news .left .title {font-size: 20px;
}
.news .left .info {color: #999999;
}
.news .left .info span {margin-right: 20px;
}
.news .right {width: 160px;height: 120px;
}
.news .right img {width: 100%;height: 100%;object-fit: cover;
}
</style>


插槽

他本身就还是个组件,只不过是活的,可定制的

类别1:默认插槽

在这里插入图片描述



是写在子组件里的
在这里插入图片描述

MyDialog2.vue          子组件是

<template><div class="MyDialog2"><div class="log-header"><h1>友情提示</h1><span>✖️</span></div><hr /><div class="log-body"><slot></slot></div><div class="log-footer"><button class="cancel">取消</button><button class="ok">确认</button></div></div>
</template><script>
export default {}
</script><style scoped>
* {margin: 0;padding: 0;box-sizing: border-box;
}
.MyDialog2 {width: 400px;margin: 20px auto;padding: 0 20px;border: 1px black solid;border-radius: 10px;background-color: #fff;
}
.log-header {height: 60px;display: flex;justify-content: space-between;line-height: 60px;
}.log-body {padding: 10px;height: 80px;
}.log-footer {display: flex;justify-content: flex-end;padding-bottom: 10px;
}button.cancel {width: 50px;height: 30px;background-color: #fff;margin-right: 20px;border: black 1px solid;border-radius: 5px;
}button.ok {width: 50px;height: 30px;background-color: #05defa;border: black 1px solid;border-radius: 5px;
}
</style>


App.vue
<template><div class="app"><!-- 直接写 不用{{}} --><MyDialog2>确认删除吗 </MyDialog2><MyDialog2>确认退出吗 </MyDialog2></div>
</template><script>
import MyDialog2 from './components/MyDialog2.vue'
export default {components: {MyDialog2}
}
</script><style>
body {background-color: #cac2c2;
}
</style>


后备内容(有默认值的)

在这里插入图片描述


在这里插入图片描述




MyDialog.vue

<div class="log-body"><slot>有后备内容</slot></div>


Vue.vue

    <div class="app"><!-- 有数值,就照常显示 --><MyDialog2>确认删除吗 </MyDialog2><MyDialog2>确认退出吗 </MyDialog2><!-- 没数值,就显示默认 --><MyDialog2> </MyDialog2></div>


类别2:具名插槽

在这里插入图片描述



在这里插入图片描述


MyDialog2.vue               子组件

 <div class="MyDialog2"><div class="log-header"><slot name="head"></slot></div><hr /><div class="log-body"><slot name="body">有后备内容</slot></div><div class="log-footer"><slot name="footer"></slot></div></div>


App.vue 父组件