Nuxt3中封装阿里云播放器

506 阅读10分钟

image.png

【成品镇楼】

vue项目中相信好多兄弟都封装过阿里云的播放器了,但是Nuxt中呢?

组件应该也能在vue3中使用,有问题的兄弟们一楼发下问题哈。我这里没有vue环境就不测试了

官网代码示例

aliplayer官网传送门

选择在线配置选项卡,经过一系列的配置,我们得到了这样一段代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge" >
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Aliplayer Online Settings</title>
<link rel="stylesheet" href="https://g.alicdn.com/apsara-media-box/imp-web-player/2.21.0/skins/default/aliplayer-min.css" />
<script type="text/javascript" charset="utf-8" src="https://g.alicdn.com/apsara-media-box/imp-web-player/2.21.0/aliplayer-min.js"></script>
</head>
<body>
<div class="prism-player" id="player-con"></div>
<script>
var player = new Aliplayer({
  "id": "player-con",
  "source": "//player.alicdn.com/video/aliyunmedia.mp4",
  "width": "100%",
  "height": "500px",
  "autoplay": true,
  "isLive": false,
  "rePlay": false,
  "playsinline": true,
  "preload": true,
  "controlBarVisibility": "hover",
  "useH5Prism": true
}, function (player) {
    console.log("The player is created");
  }
);
</script>
</body>

这是官网给出的基础示例,它在HTML文档中引入了阿里云播放器的CSS样式表和JavaScript脚本,并在页面加载完成后立即初始化播放器。

  • <meta> 标签:设置字符集、浏览器兼容性和视图端口。这些设置确保页面在不同设备和浏览器上正确显示。
  • <link> 标签:引入阿里云播放器的CSS样式表,负责播放器的外观和样式。
  • <script> 标签:引入阿里云播放器的JavaScript库,这是播放器功能实现的核心。
  • <div class="prism-player" id="player-con"></div>:定义一个容器,用于承载视频播放器。id属性用于在JavaScript中引用这个容器。

JavaScript初始化播放器

var player = new Aliplayer({
  "id": "player-con",
  "source": "//player.alicdn.com/video/aliyunmedia.mp4",
  "width": "100%",
  "height": "500px",
  "autoplay": true,
  "isLive": false,
  "rePlay": false,
  "playsinline": true,
  "preload": true,
  "controlBarVisibility": "hover",
  "useH5Prism": true
}, function (player) {
    console.log("The player is created");
});

这段代码通过new Aliplayer({...})实例化一个新的播放器对象。它接受两个参数:

  1. 配置对象:包含播放器的配置选项,如容器ID(id)、视频源(source)、宽度(width)、高度(height)、是否自动播放(autoplay)等。
  2. 回调函数:在播放器创建完成后执行。这里仅用于在控制台输出一条消息表示播放器已创建。

注意

  • 视频源(source)使用了协议相对URL(//player.alicdn.com/video/aliyunmedia.mp4),这意味着它会根据当前页面的协议(HTTP或HTTPS)来请求视频资源。这是一种避免混合内容警告的好方法,特别是在HTTPS网站上。

我们可以用相同的思路来实现一下

加载CSS/JS方案选择

DOM方案

我第一想到的就是document.createElement和document.body.appendChild的组合,这对简直是万金油的存在。

document.createElementdocument.body.appendChild是JavaScript中操作DOM(文档对象模型)的两个基本方法,它们在动态创建和添加页面元素时非常有用。下面分别解释这两个方法:

document.createElement

document.createElement方法用于创建一个新的元素节点。这个方法需要一个字符串参数,该参数指定了要创建的元素的类型,比如'div''span''a'等。创建的元素是一个DOM节点,可以通过JavaScript进一步操作(比如设置属性、添加事件监听器等),但在这一步还没有添加到文档(页面)中。

语法

let element = document.createElement(tagName);
  • tagName:要创建的元素的名称(如'div''span'等)。

示例

let div = document.createElement('div');

这行代码创建了一个新的<div>元素,但这个<div>元素此时还不在页面上显示。

document.body.appendChild

document.body.appendChild方法用于将一个节点作为最后一个子节点添加到document.body元素中。这意味着你可以通过这个方法把一个元素实际添加到页面的<body>部分,从而使其显示在页面上。

语法

document.body.appendChild(child);
  • child:要添加到document.body中的节点。

示例

document.body.appendChild(div);

假设div是之前通过document.createElement('div')创建的<div>元素。这行代码会将div元素添加到页面的<body>部分的末尾,此时<div>元素就会在页面上显示出来。

结合使用

document.createElementdocument.body.appendChild经常一起使用,先创建一个元素,然后将其添加到页面中。例如,动态添加一个段落(<p>)到页面的流程是这样的:

// 创建一个新的<p>元素
let p = document.createElement('p');
// 设置一些属性,例如文本内容
p.textContent = 'Hello, world!';
// 将<p>元素添加到<body>的末尾
document.body.appendChild(p);

这样,一个包含文本“Hello, world!”的段落就会被添加到页面的底部。这种方式非常灵活,允许开发者通过JavaScript动态地修改页面内容。

具体方案

<template>
  <div>
    <div class="prism-player" id="player-con"></div>
  </div>
</template>

<script setup lang="ts">
import { onMounted } from "vue";
declare var Aliplayer: any;
const props = withDefaults(
  defineProps<{
    url: string;
  }>(),
  { url: "//player.alicdn.com/video/aliyunmedia.mp4" }
);
// 初始化播放器
function initPlayer() {
  var player = new Aliplayer(
    {
      id: "player-con",
      source: props.url,
      width: "100%",
      height: "500px",
      autoplay: true,
      isLive: true,
      rePlay: false,
      playsinline: true,
      preload: true,
      controlBarVisibility: "hover",
      useH5Prism: true,
    },
    function (player: any) {
      console.log("The player is created");
    }
  );
}
const init = async () => {
  // 动态加载Aliplayer的CSS和JS
  const cssLink = document.createElement("link");
  cssLink.href =
    "//g.alicdn.com/apsara-media-box/imp-web-player/2.21.0/skins/default/aliplayer-min.css";
  cssLink.rel = "stylesheet";
  document.head.appendChild(cssLink);

  const script = document.createElement("script");
  script.src =
    "//g.alicdn.com/apsara-media-box/imp-web-player/2.21.0/aliplayer-min.js";
  script.onload = () => initPlayer();
  document.body.appendChild(script);
};
onMounted(() => {
   init();
});
</script>

<style scoped>
/* 如果你需要一些特定的样式,可以在这里添加 */
</style>

Nuxt3 useHead方案

useHead是Nuxt 3提供的一个Composition API函数,它允许你在Vue组件中以声明式的方式管理和更新页面的头部(<head>)信息。这包括但不限于修改页面的标题、描述、添加外部资源链接(如CSS和JavaScript文件)、设置元数据(meta tags)等。useHead的设计初衷是为了提供一种更简洁、更易于维护的方式来处理页面头部信息,尤其是在需要根据组件的状态或者路由动态改变头部信息的场景中。

基本使用

useHead函数接收一个对象作为参数,这个对象定义了你想要添加到页面头部的所有信息。这里是一些基本的用法示例:

<script setup>
useHead({
  title: 'My Awesome App',
  meta: [
    {
      name: 'description',
      content: 'This is an awesome application made with Nuxt 3'
    }
  ],
  link: [
    {
      rel: 'stylesheet',
      href: 'https://example.com/style.css'
    }
  ],
  script: [
    {
      src: 'https://example.com/script.js',
      async: true
    }
  ]
})
</script>

在这个示例中,useHead被用来设置页面标题、一个meta标签(描述页面内容的描述信息)、一个外部CSS文件和一个异步加载的外部JavaScript文件。

动态头部信息

useHead也支持动态头部信息,这意味着你可以基于组件的状态或者响应式引用来改变头部信息。例如,如果你想根据文章的标题动态设置页面标题,可以这样做:

<script setup>

const articleTitle = ref('Default Title')

useHead({
  title: computed(() => `${articleTitle.value} - My Blog`)
})
</script>

这里,页面的标题会根据articleTitle的值动态更新。

服务端渲染(SSR)

Nuxt 3支持服务端渲染,useHead在这种情况下特别有用,因为它可以确保即使在服务器端渲染页面时,头部信息也能正确设置和发送给客户端。这对于SEO(搜索引擎优化)和提升用户体验非常重要。

注意

在Nuxt 3中,useHead是推荐的API,用于管理和更新页面的头部(<head>)信息。而useMeta是Nuxt 2中用于类似目的的API,但在Nuxt 3的早期版本中,它也曾短暂出现。随着Nuxt 3的发展,useHead成为了官方推荐的方式,因为它提供了更灵活和强大的功能来处理头部信息。

具体实现

<template>
  <div>
    <div class="prism-player" id="player-con"></div>
  </div>
</template>

<script setup lang="ts">
declare var Aliplayer: any;
const props = withDefaults(
  defineProps<{
    url: string;
  }>(),
  { url: "//player.alicdn.com/video/aliyunmedia.mp4" }
);
useHead({
  link: [
    {
      rel: "stylesheet",
      href: "//g.alicdn.com/apsara-media-box/imp-web-player/2.21.0/skins/default/aliplayer-min.css",
    },
  ],
  script: [
    {
      src: "//g.alicdn.com/apsara-media-box/imp-web-player/2.21.0/aliplayer-min.js",
      async: true, // 如果你希望脚本异步加载
      defer: true, // 如果你希望脚本在文档解析完成后,延迟执行
      type: "text/javascript",
    },
  ],
});
// 初始化播放器
function initPlayer() {
  var player = new Aliplayer(
    {
      id: "player-con",
      source: props.url,
      width: "100%",
      height: "500px",
      autoplay: true,
      isLive: true,
      rePlay: false,
      playsinline: true,
      preload: true,
      controlBarVisibility: "hover",
      useH5Prism: true,
    },
    function (player: any) {
      console.log("The player is created");
    }
  );
}

onMounted(() => {
  initPlayer();
});
</script>

<style scoped>
/* 如果你需要一些特定的样式,可以在这里添加 */
</style>

最终选择

在Nuxt 3项目中,使用 useHead 是一个更现代的方法来动态管理页面的头部信息,包括外部 CSS 和 JS 文件。这样做有几个明显的优势:

  1. 声明式的方式useHead 提供了一种声明式的方式来指定页面头部应该包含哪些资源。这使得代码更加简洁和易于维护。
  2. 响应式useHead 可以和 Vue 的响应式系统一起工作,这意味着你可以根据组件的状态动态更改头部信息。
  3. SSR 友好:Nuxt 3 旨在支持服务端渲染(SSR),使用 useHead 可以确保在服务器渲染页面时正确地设置头部信息,这对 SEO 非常重要。
  4. 性能优化useHead 允许你设置 asyncdefer 属性,这有助于优化加载性能,因为它允许浏览器非阻塞地加载外部脚本。
  5. 避免全局污染:通过 useHead 加载的脚本和样式表仅限于组件的生命周期,这有助于避免全局作用域的污染。
  6. 更好的控制useHead 可以让你更精细地控制资源的加载时机和方式,例如仅在特定路由下加载某些脚本。

相比之下,使用 document.createElementdocument.body.appendChild 的传统 DOM 操作方式虽然灵活,但它并不是响应式的,也不太适合用于服务端渲染的环境。此外,这种方式可能会引入更多的运行时错误,比如重复添加同一个脚本,或者在组件销毁时未能清理掉动态添加的元素,从而导致内存泄漏。

因此,在 Nuxt 3 项目中,推荐使用 useHead 来动态加载外部 CSS 和 JS 文件。这不仅遵循了 Vue 3 和 Nuxt 3 的最佳实践,还能带来更好的性能和更优的开发体验。

组件改造

在Nuxt 3项目中,为了使Aliplayer的参数更加灵活和可配置,同时遵循Vue 3的最佳实践,我们可以将播放器的配置参数作为组件的属性来传递。这样,使用组件的开发者可以通过属性来定制播放器的行为,使组件更加通用和灵活。

以下是如何改进这个组件,以便接收更多Aliplayer配置参数的示例:

步骤 1: 定义Props

首先,定义一个接收更多Aliplayer配置的props。使用defineProps来声明这些属性,并为它们提供类型定义和默认值。

// 在<script setup lang="ts">中
import { defineProps, onMounted } from 'vue';

// 定义一个类型接口用于Props
interface AliplayerProps {
  url: string;
  autoplay?: boolean;
  isLive?: boolean;
  rePlay?: boolean;
  playsinline?: boolean;
  preload?: boolean;
  controlBarVisibility?: string;
  useH5Prism?: boolean;
  width?: string;
  height?: string;
  // 可以根据需要添加更多Aliplayer支持的配置项
}

// 使用defineProps定义组件的props
const props = withDefaults(defineProps<AliplayerProps>(), {
  url: '//player.alicdn.com/video/aliyunmedia.mp4', // 默认视频URL
  autoplay: true,
  isLive: false,
  rePlay: false,
  playsinline: true,
  preload: true,
  controlBarVisibility: 'hover',
  useH5Prism: true,
  width: '100%',
  height: '500px',
  // 设置其他默认值
});

步骤 2: 动态传递Props到Aliplayer

修改initPlayer函数,使其能够接受从props传递过来的参数,从而动态配置Aliplayer。

function initPlayer() {
  const player = new Aliplayer({
    id: 'player-con',
    source: props.url,
    autoplay: props.autoplay,
    isLive: props.isLive,
    rePlay: props.rePlay,
    playsinline: props.playsinline,
    preload: props.preload,
    controlBarVisibility: props.controlBarVisibility,
    useH5Prism: props.useH5Prism,
    width: props.width,
    height: props.height,
    // 传递其他配置项
  }, function(player: any) {
    console.log('The player is created');
  });
}

步骤 3: 在模板中使用组件

现在,当你在Nuxt 3应用中或其他Vue 3项目中使用这个组件时,可以像这样传递自定义的属性:

<AliplayerComponent
  :url="'your-video-url.mp4'"
  :autoplay="true"
  :isLive="false"
  :width="'640px'"
  :height="'360px'"
  // 传递其他需要的配置
/>

这种方式使得Aliplayer组件更加灵活和可配置,同时保持了代码的简洁和可维护性。通过将配置参数作为组件的属性传递,可以轻松地在不同场景下重用和定制视频播放器,满足不同需求。

写在后面

css就不写了啊,两个脚本引入方案我都试过了。都是OK的

下班啦~~~

放假啦~~~