前言
若有新知识点会在这边加入的
注意:以下的知识点,并非以文档或者别人的博客为准的,只是我这边使用的场景为准,均以本人自己的学习和研究得理解出来的,如有错误或者疑问可以自行去下面的链接[vue3文档]查看或者谷歌等搜索
vue3文档
\
常用应用API
import { createApp } from 'vue'
const app = createApp({})
//调用 createApp 返回一个应用实例。该实例提供了一个应用上下文。应用实例挂载的整个组件树共享相同的上下文
app.use({Object | Function} plugin]) //实例化一个对象或者方法的插件,用法如下
app.use(List) //以vant ui中的List组件为例,当使用此方法时,即可全局使用List组件
//注册全局组件
app.component('要使用的组件名称',被导入的组件名)
//根组件实例,将应用实例的根组件挂载在提供的 DOM 元素上。
app.mount('#app')
//在应用程序内的任何组件实例中访问的全局 property。属性名冲突时,组件的 property 将具有优先权。
import daysJs from 'dayjs'
//在vue2里面添加全局变量方式如下
Vue.prototype.daysJs=daysJs
//调用
console.log(this.daysJs)
//在vue3里面添加全局变量方式如下(限在开发环境下,生产环境建议不要使用)
app.config.globalProperties.key=()=>console.log('逻辑体')
app.config.globalProperties.daysJs = daysJs;
//调用
setup(){
const {ctx} =getCurrentInstance()
console.log(ctx.daysJs)
}
常用全局API
//nextTick 更改了一些数据以等待 DOM 更新后立即使用它
//用法
import {nextTick} from 'vue'
await nextTick()
console.log('nextTick数据修改了')
常用新内置API
<!--teleport 指定将在其中移动 <teleport> 内容的目标元素-->
//示例
<!-- 正确 -->
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />
<!-- 错误 -->
<teleport to="h1" />
<teleport to="some-string" />
<!--disabled - boolean。此可选属性可用于禁用 <teleport> 的功能,这意味着其插槽内容将不会移动到任何位置,而是在您在周围父组件中指定了 <teleport> 的位置渲染。-->
<teleport to="#popup" :disabled="displayVideoInline">
其他模板
</teleport>
组合式 API
//setup 用于组件式api的入口 条件可以接收(0个或者最多2个参数的情况)
//注意在setup()方法前使用如下格式是不允许的,因为setup(){}函数 不属于异步操作,不能使用async这种方式去处理数据
async setup(){
}
//示例
setup(){
return {
}
}
//当使用 setup 函数时,它将接受两个参数:
/*
1.props
2.context
*/
// props setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。
//注意,因为 props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性。
export default{
props:{
list:{
type:Array,
default(){
return []
}
}
},
setup(props){
console.log(props.list)
return {
}
}
}
//如果需要解构 prop,可以通过使用 setup 函数中的 toRefs 来完成此操作
import { toRefs } from 'vue'
export default{
props:{
list:{
type:Array,
default(){
return []
}
}
},
setup(props){
const {list} = toRefs(props)
console.log(list.value)
return {
}
}
}
//传递给 setup 函数的第二个参数是 context。context 是一个普通的 JavaScript 对象,它暴露组件的三个 property:
setup(props,context){
// Attribute (非响应式对象)
console.log(context.attrs)
// 插槽 (非响应式对象)
console.log(context.slots)
// 触发事件 (方法)
console.log(context.emit)
//解构方式
const {emit,slots,attrs} = context
return {
}
}
//
生命周期钩子
import { onActivated,onDeactivated,onErrorCaptured
,onBeforeMount, onRenderTracked, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onRenderTriggered }
setup() {
onBeforeMount(()=>{
console.log('在挂载开始之前被调用:相关的 render 函数首次被调用。')
})
//例子
onBeforeMount(()=>{
horizontalBsScroll = null
})
onRenderTracked(()=>{
console.log('是render函数首次被重新调用时触发')
})
onRenderTriggered(()=>{
console.log('是render函数被重新调用时触发')
})
onMounted(()=>{
console.log('组件挂载完成后执行的函数')
})
//例子
onMounted(async ()=>{
await 调用接口方法()
})
onBeforeUpdate(()=>{
console.log('组件更新之前执行的函数。')
})
onUpdated(()=>{
console.log('组件更新完成之后执行的函数')
})
onBeforeUnmount(()=>{
console.log('组件卸载之前执行的函数')
})
onUnmounted(()=>{
console.log('组件卸载完成后执行的函数')
})
//例子
onUnmounted(()=>{
horizontalBsScroll.destroy()
})
onActivated(()=>{
console.log('被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行')
})
onDeactivated(()=>{
console.log('比如从 A 组件,切换到 B 组件,A 组件消失时执行。')
})
onErrorCaptured(()=>{
console.log(' 当捕获一个来自子孙组件的异常时激活钩子函数)')
})
}
响应式 API
//reactive 返回对象的响应式副本
//例子
const obj = reactive({
list:[],
data:{}
})
//ref 接受一个内部值并返回一个响应式且可变的 ref 对象
const count = ref(0)
console.log(count.value) // 0
//注意:在模板中使用ref变量时,无需带上.value方式,因为vue底层已经处理了模块中.value问题,可以直接使用如下
{{count}}
//如果在js中使用,需要加上.value这个进行相应的操作
count.value++
//若要处理refs这种情况,需要如下的情况
//首先先在模板中创建一个名字
<div ref="div"></div>
//在js中使用
setup(){
const div=ref(null)
onMounted(()=>{
console.log(div.value)
})
return {
div
}
}
//Computed
//接受一个 getter 函数,并为从 getter 返回的值返回一个不变的响应式 ref 对象。
//例子
const dayTime = computed(()=>{
const d=new Date()
return d.getDate()
})
//是否禁用按钮
const isDisabled = computed(()=>(password.value.length)?false:true)
//watch
//侦听一个单一源
//监听切换的状态
watch(artis, (count, prevCount) => {
console.log(count,prevCount)
})
//侦听多个源
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
console.log('返回的数据结果')
})
hooks的使用(直接以几个例子解释)
//创建hooks的示例
import {onMounted, ref, onUnmounted, watch,onBeforeMount ,nextTick,onUpdated,reactive } from'vue'
import BScroll from 'better-scroll'
function horizontalHooksBsScroll(){
const horizontalScroll = ref(null)
let horizontalBsScroll = null
onBeforeMount(()=>{
horizontalBsScroll = null
})
onUnmounted(()=>{
horizontalBsScroll.destroy()
})
onMounted(()=> {
horizontalBsScroll = new BScroll(horizontalScroll.value, {
scrollX: true,
probeType: 3,
click: true
})
return _registerHooks(['scroll','scrollEnd'], (pos) => {
console.log(pos,'done')
})
})
onUpdated(async()=>{
await nextTick()
bsRefresh()
})
watch(horizontalScroll,()=>{
bsRefresh()
})
const _registerHooks = (hookNames, handler)=>{
hookNames.forEach((name) => {
horizontalBsScroll.on(name, handler)
})
}
//页面加载,去重置
function bsRefresh(){
horizontalBsScroll.refresh()
}
return horizontalScroll
}
export default horizontalHooksBsScroll
//调用(a.vue)
import horizontalHooksBsScroll from './hooks/useHorizontalScroll'
setup(){
const horizontalScroll = horizontalHooksBsScroll()
return {
horizontalScroll
}
}
//videoHooks.js
import {ref,reactive,onMounted,computed,nextTick,onUnmounted} from 'vue'
import {useRoute} from 'vue-router'
let audioInterval;
function realFormatSecond(second) {
const secondType = typeof second
if (secondType === 'number' || secondType === 'string') {
second = parseInt(second)
// var hours = Math.floor(second / 3600)
// second = second - hours * 3600
const _second = second
var mimute = Math.floor(second / 60)
const a_second = _second - mimute * 60
return ('0' + mimute).slice(-2) + ':' + ('0' + a_second).slice(-2)
} else {
return '00:00'
}
}
const videoMvHooks = ()=>{
const route = useRoute()
const videoRefPlay = ref(null) //操作时
const detail =reactive({
url:'', //要播放的mv地址
data:{},//其他消息
info:{},//转的数据
})
const videoData =reactive({
audioTime:0,//音频进度百分比
audioCurrentTime:'00:00',//音频当前播放时间
audioAllTime:'00:00',//音频总播放时间
audioAllDuration:0,//音频总播放秒数
bsize:`var(--f8)`,//默认为8
onOff: true, // 控制播放暂停按钮
isAutoplay:true,//是否要自动播放
brsShow:false,//清晰度调整
br:1080,//默认清晰度为1080
artistsShow:false,//查看更多作用
})
//开始时间
const startTimer =computed(()=>{
return videoData.audioCurrentTime
})
//结束时间
const endTimer =computed(()=>{
return videoData.audioAllTime
})
//动态创建video标签
const videoCreated = (url)=>{
const x = document.createElement("VIDEO");
x.setAttribute("width", "100%");
x.setAttribute("class", "video-wrap");
x.setAttribute("id", "videoWrap");
x.setAttribute("max-height", "320");
x.setAttribute("controls", false);
x.setAttribute("show-mute-btn", true);
x.setAttribute("muted", true);
x.setAttribute("loop ", true);
x.setAttribute("x5-video-player-type", 'h5');
x.setAttribute("object-fit", 'contain');
x.setAttribute("custom-cache", false);
x.setAttribute("show-center-play-btn", false);
x.setAttribute("autoplay", true);
x.setAttribute("x5-playsinline", true);
x.setAttribute("webkit-playsinline", true);
x.setAttribute("ref", 'videoRefPlay');
x.setAttribute("src", url);
x.onContextMenu =()=>{
return false
}
x.onClick =()=>{
onPlayVidoPause()
return false
}
document.body.appendChild(x);
document.getElementById("demo").innerHTML = "<b>注释:</b>IE 和 Safari 不支持 .ogg 文件格式。这只是一个例子。如需使其在所有浏览器中运行,您应该在 video 元素中使用 source 元素。";
}
//点击视频暂停
const onPlayVidoPause= ()=>{
const _audioPlayer=document.getElementById('videoWrap')
if(_audioPlayer?.play){
videoData.onOff = true
_audioPlayer.pause()
}
}
//设置定时检测
const setAudioInterval=()=>{
const _audioPlayer=document.getElementById('videoWrap')
videoData.onOff = false
if(_audioPlayer.play){
audioInterval = setInterval(()=>{
getAudiTime()
if(_audioPlayer.ended){
clearInterval(audioInterval)
videoData.audioTime = 0
_audioPlayer.currentTime = 0
videoData.audioCurrentTime ='00:00'
}
},500)
} else {
clearInterval(audioInterval)
}
}
//视频的其他变化
const getAudiTime = ()=>{
const _audioPlayer=document.getElementById('videoWrap')
videoData.audioAllTime=realFormatSecond(_audioPlayer.duration)
videoData.audioAllDuration =_audioPlayer.duration
videoData.audioCurrentTime = realFormatSecond(_audioPlayer.currentTime)
videoData.audioTime =(_audioPlayer.currentTime*100/_audioPlayer.duration).toFixed(3)
}
//进度变化时实时触发
const onChange=value =>{
const _audioPlayer=document.getElementById('videoWrap')
videoData.audioCurrentTime = realFormatSecond(videoData.audioAllDuration*value/100)
_audioPlayer.currentTime = parseInt(videoData.audioAllDuration*value/100)
_audioPlayer.play()
if(_audioPlayer.play){
videoData.onOff = false
}
}
const onInput = value=>{
videoData.onOff = false
}
//开始拖动时触发
const onDragStart = ()=>{
videoData.onOff = false
}
//结束拖动时触发
const onDragEnd = ()=>{
const _audioPlayer=document.getElementById('videoWrap')
videoData.onOff = false
_audioPlayer.play()
}
//开始播放
const onPlayVideo = ()=>{
const _audioPlayer=document.getElementById('videoWrap')
if(_audioPlayer.pause){
videoData.onOff = false
setTimeout(()=>{
_audioPlayer.play()
},150)
}
}
//重置
const onRestPlay=(br)=>{
videoData.br =br
videoData.brsShow = false
videoData.audioTime=0
videoData.audioCurrentTime='00:00'
videoData.audioAllTime='00:00'
videoData.audioAllDuration=0
}
onUnmounted(()=>{
clearInterval(audioInterval)
onPlayVidoPause()
})
return {
route,videoRefPlay,detail,
startTimer,endTimer,videoCreated,
onPlayVidoPause,setAudioInterval
,getAudiTime,onChange,onDragStart,
onDragEnd,onPlayVideo,onRestPlay,videoData,onInput
}
}
export default videoMvHooks
//调用a.vue
import videoHooks from '@/hooks/videoHooks'
setup(){
const {
route,videoRefPlay,detail,
startTimer,endTimer,videoCreated,
onPlayVidoPause,setAudioInterval
,onChange,onDragStart,
onDragEnd,onPlayVideo,videoData,onInput
} = videoHooks();
return {
route,videoRefPlay,detail,
startTimer,endTimer,videoCreated,
onPlayVidoPause,setAudioInterval
,onChange,onDragStart,
onDragEnd,onPlayVideo,videoData,onInput
}
}