Vue3 最快最全上手学习教程!

2,582 阅读10分钟

Vue3

Vue3 CDN

Vue3 中文文档:

vue3js.cn/docs/zh/

Vue 社区

vue3js.cn/

Vue2 参考,学习笔记

Vue2 的学习

一、 初识 Vue3.0

建议先学习完 Vue2、vue-router、vuex 、vue-cli 再学习 Vue3

1. Vue3 的一大特性函数 ---- setup

 1、setup 函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之间的函数 也就说在 setup函数中是无法 使用 data 和 methods 中的数据和方法的。
 2、setup 函数是 Composition API(组合API)的入口。
 3、在setup 函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用。
4、setup 函数只能是同步而不能是异步的。

1. setup(Composition API) 的学习

首先要知道,在 Vue3 里是兼容 Vue2 语法的,也就是说,可以使用 data,methods 等等。虽然使用 Vue2 的语法不会报错,但是,Vue3 就该使用 Vue3 的语法。
在 Vue2 里我们要定义数据和方法都得在 data 和 methods 里,其他定义组件,计算属性,监听数据等等,Vue2 都给我们规定死了。而在 Vue3 中不同,Vue3 中所有的操作都放在了 setup 中,并且定义数据及方法都与 Vue2 不同,其他定义组件,计算属性,监听数据等等在 setup 中变为了按需引入,即使用时需要 import 将其引入才可用。

<template>
	// ...
</template>

<script>
  
export default {
  // Vue2 接受父组件数据
  props:{
  	name: String,
    age:{
    	type: Number,
      default: 18
    }
  },
  // props 为接受的父组件数据
  // ctx 本组件上下执行文
  setup(props, ctx){
    console.log(props.name)
    console.log(ctx)
    return {}
  }
}
</script>

1. reactive 定义响应式数据

使用方法:

<template>
  // 使用
  <p>{{ state.id }}</p>
</template>

<script>
 // 引入 reactive 
import { reactive } from 'vue'
  
export default {
  setup(props, ctx){
    // 定义 state 存放 reactive 声明的数据
    const state = reactive({
        id: 1
      }
    )

    return {
      // 最后需要将其返回
      state
    }
  }
}
</script>

页面效果:
image.png


2. 定义方法

在 Vue3 里定义方法不需要引入,直接使用变量定义函数的方式即可,但同样需要将定义好的方法返回。

<template>
  // 使用
  <p>{{ state.id }}</p>
// 添加方法
<button @click='add()'>增加</button>
</template>

<script>
 // 引入 reactive 
import { reactive } from 'vue'
  
export default {
  setup(props, ctx){
    // 定义 state 存放 reactive 声明的数据
    const state = reactive({
        id: 1
      }
    )
    // 定义方法
    const add = () => {
      state.id++
    }

    return {
      // 最后需要将其返回
      state,
      add
    }
  }
}
</script>

如果没有返回

image.png

效果:
Vue3定义方法.gif
可能有人问了?我每次在外面使用数据都得state.id吗?那不是很麻烦吗?不不不,这里可以使用ES6的展开运算符,将state里的数据映射出去,就可以直接输入定义的名称使用了。

<template>
  // 使用
  <p>{{ state.id }}</p>
// 添加方法
<button @click='add()'>增加</button>
</template>

<script>
 // 引入 reactive 
import { reactive } from 'vue'
  
export default {
  setup(props, ctx){
    // 定义 state 存放 reactive 声明的数据
    const state = reactive({
        id: 1
      }
    )
    // 定义方法
    const add = () => {
      state.id++
    }

    return {
      // ES6展开运算符返回
      ...state,
      add
    }
  }
}
</script>

然而这时候。。。你会发现一个BUG!!!那就是我们页面的数据在触发add方法后没反应了,但是我们给add方法添加一个console.log,它却照样能够自增,但是页面上的数据却不会改变?也就是说明数据并没有完成响应式:
Vue3定义方法2.gif
为什么?因为在使用展开运算符的时候,它同时会将我们的响应式给取消。
那这时候怎么办呢?

3. toRefs 保护响应式数据特性

<template>
  // 使用
  <p>{{ state.id }}</p>
// 添加方法
<button @click='add()'>增加</button>
</template>

<script>
 // 引入 reactive 
import { reactive } from 'vue'
  
export default {
  setup(props, ctx){
    // 定义 state 存放 reactive 声明的数据
    const state = reactive({
        id: 1
      }
    )
    // 定义方法
    const add = () => {
      state.id++
    }

    return {
      // 使用 toRefs
      ...toRefs(state),
      add
    }
  }
}
</script>

那么这时候,你会发现页面上的数据开始跟着变化了:
Vue3toRefs.gif

4. computed 计算属性

<p>{{ id }}----{{ name }}</p>

// 导入
import { reactive, toRefs, computed } from 'vue'

// 定义响应式数据
const state = reactive({
    id: 1,
    name: computed(() => '你好:' + state.id)
  }
)

return {
	...toRefs(state)
}

效果:
image.png

5. watch 监听数据

<p>{{ id }}----{{ name }}----{{ type }}</p>

// 导入
import { reactive, toRefs, computed, watch } from 'vue'

// 定义响应式数据
const state = reactive({
    id: 1,
    name: computed(() => '你好:' + state.id),
    type: '奇数'
  }
)
// 添加监听数据
// cur: 监听之后修改的数据,也就是 2
// old:监听之前未修改的数据,也就是 1;之后则是以此类推
watch(() => state.id, (cur, old) => {
  console.log(cur, old)
  if(cur % 2 == 0){
    state.type = '偶数'
  }else{
    state.type = '奇数'
  }
})

return {
	...toRefs(state)
}

页面效果:
Vue3watch.gif

6. Vue3 的生命周期

先来看看Vue2生命周期在3里的变化:

Vue2周期Vue3
beforeCreate-------->setup()
created -------->setup()
beforeMount-------->onBeforeMount
mounted-------->onMounted
beforeUpdate-------->onBeforeUpdate
updated-------->onUpdated
beforeDestroy-------->onBeforeUnmount
destroyed-------->onUnmounted
errorCaptured-------->onErrorCaptured

观看上图可以发现,除了 created 创建周期和 destroyed 周期在 Vue3 里改变了,其他都只是在原本的周期上加了 on ,变化总体来说并不大。

<script setup>
// 导入
import { onMounted, onUnmounted } from 'vue'

// onMounted
onMounted(() => {
  state.id++
})
// onUnmounted
onUnmounted(() => {
  console.log('你好')
})
</script>

现在进入页面:
image.png

7. 一个页面有多个方法时:

// 如果一个页面方法太多时,可以:
const methods = {
  a(){
    console.log('a')
  },
  b(){
    console.log('b')
  }
}
// onMounted
onMounted(() => {
  state.id++
  methods.a()
  methods.b()
})
// 返回
return {
  ...methods
}

效果:
image.png

8.ref 定义单个响应式数据

<script setup>
import { ref } from 'vue'
const count = ref(0)
console.log(count.value)

count.value++
console.log(count.value)
</script>

9.unref 返回目标值

目标是一个响应式数据则返回其内部值,如果只是个普通变量,则返回变量自身。

<script setup>
import { ref, unref } from 'vue'
const count = ref(1)
// 输出:1
console.log(unref(count))
</script>

10.toRef 将 reactive 响应式对象中的某个属性转为 ref 响应式数据

可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。

<script setup>
import { reactive, toref } from 'vue'
const state = reactive({
  foo: 1,
  bar: 2
})

// 转换为一个新的 ref
const fooRef = toRef(state, 'foo')

fooRef.value++
// 输出:2
console.log(state.foo)

state.foo++
// 输出:3
console.log(fooRef.value)
</script>

11.isRef 检查目标是否是一个 ref 对象

用处不多也不大...

12.watchEffect 执行函数体监听

类似 do...while。无论如何都会先执行一次函数体。

13. markRaw 标记对象为不可响应式

设置原始数据为不可响应式,即使 ref 和 reactive 将数据包装。

14. shallowReactive 创建一个响应式代理

创建一个响应式代理,但它只代理浅层对象,而不代理深层对象。

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2
  }
})

// 改变 state 本身的性质是响应式的
state.foo++
// 但是不转换嵌套对象;
isReactive(state.nested)
// 非响应式
state.nested.bar++

15. shallowReadonly 创建一个只读的响应式代理对象

同样只对浅层对象作效,深层对象可以任意修改,但不是响应式对象。

const state = shallowReadonly({
  foo: 1,
  nested: {
    bar: 2
  }
})

// 改变 state 本身的 property 将失败
state.foo++
// ...但适用于嵌套对象
isReadonly(state.nested) // false
state.nested.bar++ // 适用

16. readonly 将对象转为只读代理

将一个对象设置为只读对象。

const original = reactive({ count: 0 })

const copy = readonly(original)

watchEffect(() => {
  // 用于响应性追踪
  console.log(copy.count)
})

// 变更 original 会触发依赖于副本的侦听器
original.count++

// 变更副本将失败并导致警告
copy.count++

2. Vue3 常用 API

1. getCurrentInstance() 获取当前组件实例

<script>
// 引入 getCurrentInstance 获取组件本身
import { getCurrentInstance } from "vue"

export default {
  setup() {
    // 获取组件本身
    const instance = getCurrentInstance()
    console.log(instance)
    return {}
  },
}
</script>

2. useRoute、useRouter 获取路由信息

  1. useRoute():返回当前路由地址。等同于 $route。
  2. useRouter():返回路由实例。等同于 $router。
<script setup>
import { ref } from "vue"
import { useRoute, useRouter } from 'vue-router'

const router = useRouter()
const route = useRoute()
console.log(router)
console.log(route)
</script>

3. onBeforeRouteLeave、onBeforeRouteUpdate 导航守卫

  1. onBeforeRouteLeave():离开路由时触发。
  2. onBeforeRouteUpdate() :当前路由更新时触发
<script setup>
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'
  
//当前组件路由改变后,进行触发
onBeforeRouteUpdate((to, from)=>{
    console.log(to, from)
})

// 离开当前的组件,触发
onBeforeRouteLeave((to,from)=>{
    console.log(to, from)
})
</script>

4. useStore 获取 vuex 状态管理信息

等同于 this.$store。

  1. 在 vue3 中访问 store 和 getter。
<script>
// 在 vue3 中必须给予 store 计算属性,
// 才能保持住 store 的响应性。
import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
  setup () {
    const store = useStore()
		// 使用 store
    const count = computed(() => {
    	store.state.count
    })
    
    // 使用 getter
    const double = computed(() => {
    	store.getters.double
    })
    
    return {
      count,
      double
    }
  }
}
</script>
  1. 访问 mutation 和 action。
<script>
import { useStore } from 'vuex'

export default {
  setup () {
    const store = useStore()
    
    // 使用 mutation
		const increment = () =>{
    	store.commit('increment')
    }
    
    // 使用 action
    const asyncIncrement = () =>{
    	store.dispatch('asyncIncrement')
    }
    
    return {
      increment,
      asyncIncrement
    }
  }
}
</script>

5.app.config.globalProperties.$xxx 原型扩展

代替 vue2 的 Vue.prototype 写法。

import http from 'axios'

// Vue2 
Vue.prototy.$http = http

// Vue3
app.config.globalProperties.$http = http

6. keep-alive 新用法

在 vue3 中,keep-avlie 需要被 router-view 所嵌套,并在 keep-alive 中写上component 动态组件,设置 :is 属性。

<router-view v-slot="{ Component }">
  <keep-alive>
    <component :is="Component"></component>
  </keep-alive>
</router-view>

7. Provid 和 inject 依赖注入进行父、子、孙组件传参

在父组件中通过 Provid 对象传递的属性,无论在其子组件还是孙组件中都可以使用 inject 进行接受。可以无限级的传递下去。

  1. Provide 传递属性:

Provide: { 属性名称: 属性值 ... }

// 父组件
<template>
	// 引入的子组件
  <MyMarker />
</template>

<script>
// 从 Vue 中导入 Provide
import { Provide } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    // 导入子组件
    MyMarker
  },
  setup(){
  	// 传递属性
    provide('name', '阿尘s')
    provide('user', {
    	id: 0,
      age: 18,
      sex: '男'
    })
  }
}
</script>
  1. inject 接受属性:

inject: ['接收的属性名1', '接收的属性名2', ...]

// 子组件
<template>
	<p>{{ name }}</p>
	<p v-for="(item, key) in user" :key="key">{{ item }}</p>
</template>

<script>
// 从 vue 中导入 inject
import { inject } from 'vue'  

export default {
	setup(){
  	// 接受父组件传递的属性
  	const name = inject('name')
    const user = inject('user')
    
    return {
      name,
      user
    }
  }
}
</script>

二、

基于 setup() 函数的语法糖,在 setup() 的基础上省略了更加多的语法以及代码量,使我们的开发速度增进很多。下面介绍下它的一些特性,以及 API 的使用。

1. 外部组件导入后无需注册就可以直接使用

<template>
	<!-- 直接使用 -->
	<comp></comp>
</template>

<script setup>
// 外部组件导入后无需注册就可以直接使用
import Comp from "comps/JSXComp.vue";
</script>

2. 定义的数据和方法不用返回即可使用

<template>
	// 直接使用 state 中的 sum
  <button type="button" @click="state.sum++">sum is: {{ state.sum }}</button>
	// 直接绑定方法
	<button @click="onMethods.a()"></button>
</template>

<script setup>
// 1. 定义的响应式数据无需 return 出去就可以直接使用
const number = ref("定义的数据无需 return 出去");
const state = reactive({
  sum: 0,
  count1: "数据1",
  count2: "数据2",
});
// 在 DOM 中可以直接使用
console.log(number.value, state.count1, state.count2);

// 2. 定义的方法也无需 return 出去就可以直接使用
const onMethods = {
  a() {
    console.log("定义的方法也无需 return 出去");
  },
};
// 可直接绑定 DOM 元素
onMethods.a();
</script>

3. 省略 setup() 语句。

无需写入 export default 导出关键字,也无需 setup() 函数,就可以直接在 script 标签中写入 Vue3 代码。

<script setup>
// 代码内容...
</script>

4. 使用 defineProps 和 defineEmits 进行数据传递,事件传播。

  1. defineProps 使用方法:

const props = defineProps({ 数据名称: 数据类型, 数据名称: { type: 数据类型, default: 数据默认值 } })

  1. defineEmits 使用方法:

const emit = defineEmits(['事件一'], ['事件二'])

<script setup>
// 接收父组件传参
const props = defineProps({
  msg: String,
  msg2: {
  	type: String,
    defalut: '默认值'
  }
});

// 使用 emit 传播事件给父组件
const emit = defineEmits(["myClick"]);
// 定义方法
const onclick = () => {
  // 使用 emit 进行传播
  emit("myClick", '传参内容');
};
</script>

5. defineExpose 暴露属性

暴露自身属性于父组件中使用。

<script setup>
import { ref } from 'vue'

const a = 1
const b = ref(2)

// 暴露属性
defineExpose({
  a,
  b
})
</script>

6. useSlots 和 use Attrs 获取插槽和属性

<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>

三、Vue3 新特性

Vue3 做了那些优化?以及它的新特性

四、全局 API

1. defineComponent

代替了 Vue2 的 Vue.extend 构造函数。
其定义方法有两种,第一种是类似以往组件定义,使用 options API。

import { defineComponent } from 'vue'

const MyComponent = defineComponent({
  data() {
    return { count: 1 }
  },
  methods: {
    increment() {
      this.count++
    }
  }
})

第二种是使用 setup 函数的形式进行定义。

import { defineComponent, ref } from 'vue'

const HelloWorld = defineComponent(function HelloWorld() {
  const count = ref(0)
  return { count }
})

2. defineAsyncComponent

异步组件定义,完善了 Vue2 动态、异步、懒加载组件的用法。

  1. 使用 import 单独定义一个异步组件。
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

app.component('async-component', AsyncComp)
  1. 在页面中局部注册一个组件
import { createApp, defineAsyncComponent } from 'vue'

createApp({
  // ...
  components: {
    AsyncComponent: defineAsyncComponent(() =>
      import('./components/AsyncComponent.vue')
    )
  }
})
  1. 完整使用,定义一个高自由度的异步罪案
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent({
  // 工厂函数
  loader: () => import('./Foo.vue'),
  // 加载异步组件时要使用的组件
  loadingComponent: LoadingComponent,
  // 加载失败时要使用的组件
  errorComponent: ErrorComponent,
  // 在显示 loadingComponent 之前的延迟 | 默认值:200(单位 ms)
  delay: 200,
  // 如果提供了 timeout ,并且加载组件的时间超过了设定值,将显示错误组件
  // 默认值:Infinity(即永不超时,单位 ms)
  timeout: 3000,
  // 定义组件是否可挂起 | 默认值:true
  suspensible: false,
  /**
   *
   * @param {*} error 错误信息对象
   * @param {*} retry 一个函数,用于指示当 promise 加载器 reject 时,加载器是否应该重试
   * @param {*} fail  一个函数,指示加载程序结束退出
   * @param {*} attempts 允许的最大重试次数
   */
  onError(error, retry, fail, attempts) {
    if (error.message.match(/fetch/) && attempts <= 3) {
      // 请求发生错误时重试,最多可尝试 3 次
      retry()
    } else {
      // 注意,retry/fail 就像 promise 的 resolve/reject 一样:
      // 必须调用其中一个才能继续错误处理。
      fail()
    }
  }
})

3. defineCustomElement

与 defineComponent 相似,但 defienCustomElement 返回的是一个自定义元素。

<my-vue-element></my-vue-element>

import { defineCustomElement } from 'vue'
const MyVueElement = defineCustomElement({
  // 这里是普通的 Vue 组件选项
  props: {},
  emits: {},
  template: `...`,
  // 只用于 defineCustomElement:注入到 shadow root 中的 CSS
  styles: [`/* inlined css */`]
})
// 注册该自定义元素。
// 注册过后,页面上所有的 `<my-vue-element>` 标记会被升级。
customElements.define('my-vue-element', MyVueElement)

4. nextTick

将回调推迟到下一个 DOM 更新周期之后执行。

import { createApp, nextTick } from 'vue'

const app = createApp({
  setup() {
    const message = ref('Hello!')
    const changeMessage = async newMessage => {
      message.value = newMessage
      await nextTick()
      console.log('Now DOM is updated')
    }
  }
})

五、实例

1. 多级导航栏(Nav)

使用 vue3 制作一个显示隐藏导航栏,不用设置 css 的 display 属性,下面是部分代码。
写的时候用了阿里的 iconf 图标,这个可以自己选择使用其他图片代替,也可以一样使用阿里的 iconf 图标。

<div class="Nav">
    <ul>
      <li class="Home">
        <a @click="homeShow()">
          <i class="iconfont iconshouye1"></i>
          subnave 1
        </a>
        <ul v-show="Home">
          <li>
            <a>option 1</a>
          </li>
        </ul>
      </li>
      <li class="Address">
        <a @click="addressShow()">
          <i class="iconfont icontongxunlu"></i>
          subnave 1
        </a>
        <ul v-show="Address">
          <li>
            <a>option 1</a>
          </li>
          <li>
            <a>option 2</a>
          </li>
        </ul>
      </li>
    </ul>
</div>

<script>
export default{
  setup() {
    const nav = reactive({
      Home: false,
      Address: false
    })
    // 设置列表的显示隐藏
    const methods = {
      homeShow(){
        nav.Home = !nav.Home
      },
      addressShow(){
        nav.Address = !nav.Address
      }
    }
    // 返回
    return {
      ...toRefs(nav),
      ...methods
    }
  }
}              
</script>

效果:
Vue3多级菜单.gif

2. 轮播图(Banner)

轮播图也很简单,先声明 imgArray 保存图片,再声明个 index 控制图片显示第几张。之后再 onMounted 里添加定时器,每 1.5 秒给 index+1 就行。

 <div class="Banner">
 		<img :src="imgArray[index]" alt="图片显示错误" width="1080" height="590">
 </div>

<script>
export default{
  setup(){
    const banner = reactive({
      index: 0,
      imgArray: [
        require('../assets/img/1.png'),
        require('../assets/img/2.png'),
        require('../assets/img/3.png'),
        require('../assets/img/4.jpg')
      ]
    })

    onMounted(() => {
      setInterval(() => {
        if(banner.index >=3){
          banner.index = 0
          return false
        }
        banner.index++
      },1500)
    })

    return {
      ...toRefs(banner)
    }
  }
}
</script>

效果:
忘了录,不过效果就那样。

3. 天气查询(Weather)

也是很简单的一玩意,就调用 API 就行。引入或安装 axios 后,其单页面引入方式如 Vue2相同,如果是想要全局配置,得使用

app.config.globalProperties.axios = 'axios'

官网地址:vue3js.cn/docs/zh/api…
代码:

<div class="Weather">
    <input type="text" v-model="inputData">
    <input type="button" value="查询" @click="searchSelect()">
    <p>
        <a @click="select('上海')">上海</a>
        <a @click="select('北京')">北京</a>
        <a @click="select('四川')">四川</a>
        <a @click="select('武汉')">武汉</a>
    </p>
    <div v-show="show">
        <p>查询城市:{{ city }}</p>
        <p>小提醒:{{ ganmao }}</p>
    </div>
    <ul>
        <li v-for="(item, key) in data" :key="key">
            <p>日期:{{ item.date }}</p>
            <p>天气:{{ item.type }}</p>
            <p>温度:{{ item.high }}~{{ item.low }}</p>
        </li>
    </ul>
</div>

<script>
export default{
	setup(){
  	const weather = reactive({
    	// 用户输入的城市信息
    	inputData: '',
    	// 存储查询的城市
    	city: '',
    	// 存储查询到的提示信息
    	ganmao: '',
    	// 存储查询的天气信息
    	data: [],
    	// 控制详细信息显示隐藏
    	show: false
    )}
   	// 定义方法
    const methods = {
    	// 点击按钮查询
    	searchSelect(){
    		if(weather.inputData == ''){
    		 	alert('为空你查什么?')
    		 	return false
    		}
    		/*
    		    请求地址:http://wthrcdn.etouch.cn/weather_mini
    		    请求方法:get
    		    请求参数:city(城市名)
    		    响应内容:天气信息
    		*/
    		axios.get('http://wthrcdn.etouch.cn/weather_mini?city=' + weather.inputData)
    		.then(res => {
    			// 因为这个 APi 无论查什么都会成功返回 200,所以我查了下规律
    			// 发现所有查不到城市天气信息的都会返回 1002 
    			if(res.data.status == 1002){
    				console.log(res)
    				alert('查了个什么玩意?')
    				return false
    			}
    			// 获取查找到的天气信息
    			weather.data = res.data.data.forecast
    			// 获取目前查找的城市
    			weather.city = res.data.data.city
    			// 存储查询到的提示信息
    			weather.ganmao = res.data.data.ganmao
    			// 显示详细信息
    			weather.show = true
    		})
    	},
    	// 固定城市查询
    	select(city){
    		axios.get('http://wthrcdn.etouch.cn/weather_mini?city=' + city)
    		.then(res => {
    		 	// 获取查找到的天气信息
    		 	weather.data = res.data.data.forecast
    		 	// 获取目前查找的城市
    		 	weather.city = res.data.data.city
    		 	// 存储查询到的提示信息
    		 	weather.ganmao = res.data.data.ganmao
    		 	// 显示详细信息
    		 	weather.show = true
    		})
    	}
  	}
  
    return {
    	...toRefs(weather),
    	...methods
    }
	}
}
</script>

效果演示:不过...有个Bug,无法查询四川,这个是真的不知道为什么就是不能查,使用输入框输入查询都不行,也会报错。
Vue3天气查询.gif

4. 在线音乐(musicPaly)

这个就稍微有点点复杂,使用的是网易云的 Api。并且写的时候还考虑了手机端兼容性,使用了媒体查询,控制了 mv 显示的大小。且设置了切换音乐和 mv 播放时的自动暂停。以及评论区的显示隐藏功能。
主要完成了:

  • 获取、播放音乐
  • 自动播放下一首
  • 获取热门评论
  • 获取、播放Mv

效果预览:
Vue3在线音乐.gif
pc端mv:
bandicam 2021-03-17 22-58-19-397.jpg
这里先将源代码上传:
vue3.zip
使用 reactive 声明 musicPaly 对象合集,并添加 inputData 获取输入的内容
image.png
image.png
再给input回车事件和button点击事件都绑定上 searchMusic() 方法,
image.png
然后在 musicPaly 对象合集中添加 music 存放获取到的歌曲列表
image.png
之后在 searchMusic() 方法中我们使用axios请求歌曲列表,且只获取前十条(因为只是做个小demo,为了方便就只取十条做测试就行)
image.png
将 music 对象里的内容遍历出来(打马赛克的内容不用管,现在还用不着)
image.png
那么现在输入歌名获取歌曲列表的功能应该就能实现了(播放图标不用管)
image.png
再之后实现点击歌名播放音乐和自动播放下一首功能,添加 playMusic(v.id, k) 方法,并将歌曲的 id 和 key 传过去。
image.png
添加存放 歌曲播放地址 Url
image.png
添加 Html5 音乐标签,并绑定 Url 地址
image.png
通过传过来的id查找歌曲 Url
image.png
并通过 key 得知现在播放的是第几首,然后通过监听 audio 的 ended(音乐是否已播放结束)
image.png
来调用 nextPlay(isTrue) 方法
image.png
效果自测,在线音乐就写到这。(我太懒了)
之后功能可以自己下载源码查看并学习,其里面每一行代码我都写了注释的。

原文地址:www.yuque.com/docs/share/…