跳到主要内容位置
Hello! 我是张旭乾

致力于帮助你以最直观、最快速的方式学会前端开发,并希望我的个人经历对你有所启发。点击查看最新技术视频教程、实战课程、技术博客、前端资源导航、以及我的想法和生活点滴

“峰华前端工程师”账号创作者/《JavaScript 基础语法详解》作者

最新视频

网站的性能对于用户的体验以及搜索引擎排名非常重要。根据谷歌的一项研究,超过三秒才能加载的网站会让53%的移动用户放弃浏览,而对于产品相关的网站,如果页面加载速度慢,每慢一秒就会损失5%的用户转化率。可见,网页的性能优化非常重要。在本期视频中,我们将介绍一些优化网站性能的方法。

压缩文件

第一种优化方式是压缩文件。对于 HTML、CSS 和 JavaScript 这些源代码来说,它们包含大量的空格和不必要的缩进,会占据文件空间。而网络传输受到带宽的影响,可能会使得大文件加载很慢。对这些文件进行压缩之后就能够减少文件大小,提高加载速度。你可以使用一些库来压缩代码,例如使用 UglifyJS 用于压缩 JavaScript,CSS Nano 来压缩 CSS,HTML Minifier 来压缩 HTML 文件。它们可以把源代码中的空白去掉,还会把代码进行转义,以最简约的形式呈现。这种形式可能不易阅读,但是能够保证代码能够正常执行。

另外一种压缩方式是利用服务器的功能,开启 Gzip。对于 Apache 或者 Nginx 都有对应的配置来开启。

压缩图片

第二种方式是压缩图片。可以利用一些图片压缩工具,比如说 ImageOptim、TinyPNG 等等。这些工具都比较简单,直接打开之后把图片拖进去,就能够自动进行压缩。另外,对于图片文件的选择,我们一般使用 JPG 格式的图片展示照片和比较复杂的图片,PNG 用于展示带有透明度的图片,SVG 用于加载矢量的图形。

浏览器缓存

第三种优化方式是利用浏览器的缓存,避免反复请求页面。可以把不常变化的页面内容缓存起来,每次浏览器去取本地的就可以了。比如说可以把一些图片样式和 JavaScript 代码缓存起来。这个能够极大地减少数据的传输。这个可以通过后端代码来设置,或者也可以通过 Apache 或者 Nginx 服务器进行设置。

CDN

第四种方式是利用 CDN。对于一些云厂商都提供了 CDN 服务,它会把我们的网站分发到全球不同的地理位置,然后用户在访问的时候会根据他当时的位置,取最近的服务器来访问我们的网站。当然这些网站会缓存在 CDN 服务器上,在修改之后也记得要去刷新缓存。

Deffered 和 Async 的 JavaScript

第五种是使用 async 和 defer,对于一些不太重要的 JavaScript,可以对它们进行延迟加载或者异步加载,先保证HTML DOM 的渲染。async 会在 js 下载完成之后执行,而 defer 会在 HTML 解析完成之后执行。普通的 script 则会在解析到它时立即加载并等待加载完成之后执行。

CSS 预加载(关键 CSS)

第六种是使用 CSS 资源预加载,先加载最关键的 CSS,之后再延后加载不关键的 CSS,可以通过预加载来实现。

图片懒加载

第七种方式是用图片懒加载。当图片不在屏幕的时候,那么它就先不去加载。当用户滚动到一定的距离之后,再去加载图片。也就是 lazy loading。可以通过 image 标签的 loading 属性来实现。

提高代码效率

第八种方法就是优化代码的效率,使用良好的数据结构和算法,来减少程序的运行对内存的占用。

好了,这些就是网站性能优化的一些常见方法。当然,还有很多其他的方法可以自己去研究。你学会了吗?如果有帮助请三连并关注,想学更多的开发知识,可以在评论区留言,感谢观看!

网页性能优化的 8 种方式,让网站飞起来

滑动窗口是一种编程技巧,用于把多层嵌套循环平铺成单层循环,来减少时间复杂度。几年前微软中国曾经考察过这项能力。那么这个视频我们来看一下滑动窗口的实现方法。

假设有一个题目:

给定一个数组,有 5 个元素,分别是 [3, 2, -4, 6, 1],对于每 3 个连续的元素,求它们最大的和。

例如,对于这个数组,前 3 个元素 3, 2, -4, 和为 1,后面 2, -4, 6 和为 4,再后面 -4, 6, 1 和为 3,因此最大的和是 4。

如果使用最简单的暴力解题方式,我们可能会用双层循环:

  • 从第一个元素开始遍历,直到倒数第 3 个。
  • 然后再内层循环中,加上后面 2 个元素的值。
  • 之后比对最大的和。循环结束之后就得到了结果。
function burteForce(arr, windowSize) {
  if (arr.length < windowSize) {
    return null;
  }

  let maxSum = 0;
  for (let i = 0; i < arr.length - windowSize + 1; i++) {
    let tempSum = 0;
    for (let j = 0; j < windowSize; j++) {
      tempSum += arr[i + j];
    }
    maxSum = Math.max(maxSum, tempSum);
  }

  return maxSum;
}

这样的效率会比较低,因为对于每个元素,都要在内层循环中循环 3 次,如果计算更多的元素,那么就要循环更多次。

使用滑动窗口算法可以提高速度,我们用 k 表示要计算的连续的元素数量,例如这个示例里边 k = 3,它的原理是:

  • 先计算前 k 个连续的元素的和。
  • 把和保存到一个变量 maxSum 当前最大值中。再定义一个变量 tempSum 保存后面计算 k 个元素的和,用于和当前最大值进行比对。
  • 之后,我们把 k 个元素当成可视区域窗口,让它整体向右移动 1 位,来计算后面 k 个元素的和。
  • 这样计算的话,就是减掉之前窗口所在位置中第 1 个元素的值,再加上窗口新位置中,最后一个元素的值。
  • 接下来比对新的窗口的和 tempSum 和 maxSum,如果 tempSum 大于 maxSum 就更新当前最大值。
  • 重复第 3 步和后面的操作,直到达到数组的末尾就找到了最大的和。

这个是 JavaScript 代码实现:

function slidingWindow(arr, windowSize) {
  if (arr.length < windowSize) {
    return null;
  }

  let maxSum = 0;
  let tempSum = 0;

  for (let i = 0; i < windowSize; i++) {
    maxSum += arr[i];
  }

  tempSum = maxSum;
  for (let i = windowSize; i < arr.length; i++) {
    tempSum = tempSum - arr[i - windowSize] + arr[i];
    maxSum = Math.max(maxSum, tempSum);
  }

  return maxSum;
}

小结

好了,这个就是使用滑动窗口解题的过程,你学会了吗?如果有帮助请三连并关注,想学更多的开发知识,可以在评论区留言,感谢观看!

动画算法:滑动窗口,高效率的解决数组问题

上期视频我们添加了 Express.js 结合 Notion API 的后端服务,这一期我们看一下如和把 Vue 3.0 的前端应用和后端的 Express.js API 连接起来。

配置 Proxy

我们的 Express server 部署在 3001 端口,而前端应用开发时的服务器是在 3000 端口,在浏览器访问的时候会有跨域问题,那么我们可以通过 Vite 2.0 的配置文件,添加一条 Proxy 代理配置,来让 Vite 的开发服务器帮我们转发请求,以避免跨域。

  1. 打开 vite.config.js 配置文件,在 plugins 的下方定义一个 server 属性,传递给它一个对象配置:
export default defineConfig({
  plugins: [vue()],
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:3001",
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ""),
      },
    },
  },
});

在 server 配置对象中:

  • 配置 proxy 对象,设置 key 为 "/api" ,这样所有对于 /api 的请求都会交由这个代理去处理。
  • 配置 changeOrigin 为 true,发送请求的时候修改请求的 origin,避免跨域。
  • 配置 rewrite,把实际请求的 /api 这一段去掉,因为我们后端的服务 URL 中,没有 /api 这一段,它只是方便前端区分是否为调用后端的 URL。

现在服务代理就配置完了,我们尝试一下加载留言列表。

加载留言列表

我们需要在应用一加载就去请求留言列表并展示,所以在我们的应用入口组件中,需要使用生命周期回调,在里边发送请求加载留言列表数据。

  1. 打开 CommentsApp.vue 组件,把之前定义的 comments ref 的示例数据删除,只保留一个空数组:
const comments = ref([]);
  1. 定义一个异步函数 getAllComments ,请求后端数据,并把结果放到 comments ref 中:
async function getAllComments() {
  const res = await fetch("/api/comments");
  comments.value = await res.json();
}
  1. 使用 onMounted() 生命周期回调,在组件加载完成之后,调用 getAllComments() 请求留言列表数据,记得导入进来:
import { ref, onMounted } from "vue";
onMounted(() => {
  getAllComments();
});
  1. 保存一下,先在一个命令行窗口中运行 node server,启动 express 后端服务
node server
  1. 再运行 yarn dev,访问 http://localhost:3000,如果能加载到留言列表就说明成功了。

接下来,我们看一下发表留言。

发表留言和回复

发表留言和回复的事件处理逻辑保持不变,但是现在需要调用后端服务,添加到 Notion 中。那么还是在 CommentsApp.vue 文件里,找到之前定义的 addNewComment 事件处理函数,在里边我们调用 API 把留言内容发送给后台:

const addNewComment = async (content, replyTo) => {
  await fetch(`/api/comments`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      content,
      ...(replyTo && { replyTo }),
    }),
  });

  // 新增完评论后,自动获取新的评论列表
  // Notion API 有延迟,在添加完 page 之后,需要过一会才能获取到新的评论列表
  setTimeout(async () => {
    await getAllComments();
  }, 1000);
};

这个函数我们可以让发表留言和回复共用,一并处理,因为我们不需要手动维护 comments 这个列表数组了,只是发送数据给后台,而唯一不同的地方就是 body 里,是否有 replyTo 属性,那么我们可以删除之前的 addReply() 函数,给 addNewComment 函数再加上 replyTo 参数,它接收要回复的留言的 id,再给它加上 async 关键字,因为它要发送网络请求。

  • 删除里边手动维护 comments 数组的代码。这时,constructNewComment() 也没用了,一并删除。
  • 在函数里,使用 fetch() 发送一个 post 请求。
  • 设置 content-type header 为 application/json,这一步是必须的,这样 express 才能把请求 body 转换为 json 格式。
  • body 里调用 JSON.toString() 把一个 JavaScript 对象转换为 JSON 字符串,里边同样用到了扩展运算符技巧,根据 replyTo 是否有值,来决定是否添加 replyTo 属性。
  • 后面,我们使用 setTimeout() 再请求一次获取留言列表的 API,来刷新列表。

接着把 ReplyBox 标签中,对 addReply 的调用改成 addNewComment:

<ReplyBox @submit="addNewComment($event, comment.id)" />

Notion API 的问题

这里之所以用了一个 setTimeout() 是因为 Notion API 添加数据似乎并不是实时的,如果在创建一个 page 之后,立即获取 page,那么会获取不到它,只有在等待 700 毫秒或以上才能访问到,这个得看网络情况,后面我们再对这种情况优化一下,现在先实现主要功能。 ​

好了,现在我们发表留言和回复的接口也连接上了,打开咱们的页面,编写一些示例的留言,发表一下看看,稍等一会,能加到下面的列表中,就算成功了,如果好久没显示,可以把 setTimeout() 里的延迟调大一些。再接着试试回复,编写示例的回复并提交,稍等一会能加载出来,也就算是成功了。 ​

好了,这期视频我们连接了 Vue 3.0 的前端应用到我们的 Express 后端接口了,基本上实现了一个留言板的功能,后面看情况需要对它进行优化。Notion API 现在还在 Beta 阶段,有些不稳定,所以现在适合尝鲜,等它稳定了再开发一些比较重要的 APP。 ​

这个就是 Vue 3.0 与 Express.js 前后端交互的方法,你学会了吗?如果有帮助请三连,想学更多有用的前端开发知识,请关注峰华前端工程师,感谢观看!

Vue 3.0 + Express.js API 前后端交互

Vue 是一个渐进式的 UI 框架。它改变了传统的网页开发中需要使用 JS 手动操作 DOM 的开发方式。

const ele = document.querySelector("...");
ele.value = "...";

而是以组件化的形式管理页面元素的代码。这样,每个组件就形成了特殊的、类似于自定义的 HTML 元素。我们可以给它们添加独特的功能和样式,并管理数据。

<template>
  <h1>
    <a :href="blog.link">{{ blog.title }}</a>
  </h1>
  <article>
    <div>{{ blog.content }}</div>
  </article>
</template>

<script setup>
import { ref } from "vue";

const blog = ref({
  title: "Vue 3 基础教程",
  content: "Vue 3 在 Vue 2 的基础上发生了重大变化",
  link: "/vue-3-tutorial",
});
</script>

<style scoped></style>

每个组件的代码都是独立且隔离的,可以防止与其他元素的数据冲突。

<template></template>

<script setup>
blogs; // X 不能访问
</script>

<style scoped></style>

Vue 是由华人尤雨溪主导开发的,符合国人的开发习惯。现在无论是个人、中小企业还是大企业,都有 Vue 框架的影子,而它们招聘的前端工程师岗位中大部分都是 Vue 开发。这个视频我们来快速的学习一下如何使用 Vue JS 进行开发,并使用 Vite 脚手架创建项目,让你能在最短时间内上手。

创建 vue 项目(vite)

npm init vue@latest

预览项目

yarn install yarn dev

组件结构

template、script、style

为模板提供数据

展示一篇博客详情,使用 ref 定义对象,然后再 template 展示。

  • 标签之间 {{}}
  • HTML 属性 v-bind
<template>
  <h1>
    <a :href="blog.link">{{ blog.title }}</a>
  </h1>
  <article>
    <div>{{ blog.content }}</div>
  </article>
</template>

<script setup>
import { ref } from "vue";

const blog = ref({
  title: "Vue 3 基础教程",
  content: "Vue 3 在 Vue 2 的基础上发生了重大变化",
  link: "/vue-3-tutorial",
});
</script>

<style scoped></style>

条件渲染

如果内容长度大于 100,用 v-if 展示阅读原文按钮

<article>
  <div>{{ blog.content.slice(0, 100) }}</div>
  <footer v-if="blog.content.length > 100">
    <button>阅读原文</button>
  </footer>
  </article>

切换 blog.content.length > 10 看效果:

<article>
    <div>{{ blog.content }}</div>
    <footer v-if="blog.content.length > 10">
      <button>阅读原文</button>
    </footer>
  </article>

渲染列表

把博客 ref 改成数组,渲染多个博客

<template>
  <div v-for="blog in blogs">
    <h1>
      <a :href="blog.link">{{ blog.title }}</a>
    </h1>
    <article>
      <div>{{ blog.content.slice(0, 100) }}</div>
      <footer v-if="blog.content.length > 100">
        <button>阅读原文</button>
      </footer>
    </article>
  </div>
</template>

<script setup>
import { ref } from "vue";

const blogs = ref([
  {
    id: 1,
    title: "Vue 3 基础教程",
    content: "Vue 3 在 Vue 2 的基础上发生了重大变化",
    link: "/vue-3-tutorial",
  },
  {
    id: 2,
    title: "React 18 基础教程",
    content: "React 18 在 React 17 的基础上发生了重大变化",
    link: "/react-18-tutorial",
  },
  {
    id: 3,
    title: "JavaScript 基础教程",
    content: "ECMAScript 2015 在 ECMAScript 5 的基础上发生了重大变化",
    link: "/javascript-tutorial",
  },
]);
</script>

<style scoped></style>

计算属性

使用计算属性显示文章数量

<template>
  <!-- ... -->
  <h3>总共 {{ total }} 篇</h3>
</template>
<script setup>
// ...
const total = computed(() => blogs.value.length);
</script>

处理事件

可以隐藏总页数,使用事件和函数,处理按钮事件。

<template>
  <!-- .. -->
  <h3 v-if="showTotal">总共 {{ total }} 篇</h3>
  <button @click="toggleTotal">{{ showTotal ? "隐藏" : "显示" }}总数</button>
</template>

<script setup>
import { computed, ref } from "vue";

// ...

const showTotal = ref(true);

function toggleTotal() {
  showTotal.value = !showTotal.value;
}
</script>

<style scoped></style>

处理表单

v-model 绑定响应性数据,同步用户输入和 vue 状态

<template>
  <form @submit.prevent="addPost">
    <label for="blogTitle">博客标题</label>
    <input type="text" id="blogTitle" v-model="blogForm.title" />
    <label for="content">内容</label>
    <textarea
      id="content"
      cols="30"
      rows="10"
      v-model="blogForm.content"
    ></textarea>
    <label for="link">链接</label>
    <input type="text" id="link" v-model="blogForm.link" />
    <button type="submit">提交</button>
  </form>
</template>

<script setup>
import { computed, ref } from "vue";

const initialBlogForm = {
  title: "",
  content: "",
  link: "",
};
const blogForm = ref({
  ...initialBlogForm,
});

function addPost() {
  blogs.value.push({
    id: blogs.length + 1,
    ...blogForm.value,
  });
  blogForm.value = { ...initialBlogForm };
}
</script>

创建组件并定义属性

创建博客组件,把显示博客列表项放到单独的组件中。

<template>
  <div>
    <h1>
      <a :href="link">{{ title }}</a>
    </h1>
    <article>
      <div>{{ content.slice(0, 100) }}</div>
      <footer v-if="content.length > 100">
        <button>阅读原文</button>
      </footer>
    </article>
  </div>
</template>
<script setup>
defineProps(["title", "content", "link"]);
</script>

传递属性

给博客列表项组件传递数据。v-bind 传递所有

<template>
  <BlogPost v-for="blog in blogs" v-bind="blog" />
  <!-- ... -->
</template>

<script setup>
import BlogPost from "./components/BlogPost.vue";
</script>

slot

显示分享到微信按钮

BlogPost.vue

<template>
  <div>
    <!-- ... -->
    <slot></slot>
  </div>
</template>

App.vue

<BlogPost v-for="blog in blogs" v-bind="blog">
    <button>分享到微信</button>
  </BlogPost>

生命周期

模拟远程加载阅读数

BlogPost.vue

<template>
  <div>
    <article>
      <p>阅读量:{{ viewCount }}</p>
      <footer v-if="content.length > 100">
        <button>阅读原文</button>
      </footer>
    </article>
  </div>
</template>
<script setup>
const viewCount = ref(0);
onMounted(() => {
  setTimeout(() => {
    viewCount.value = 1000000;
  }, 1000);
});
</script>

自定义事件

在博客列表项里触发标题点击事件,并在 app.vue 中处理

BlogPost.vue

<template>
  <div>
    <h1>
      <a :href="link" @click.prevent="$emit('titleClick', title)">{{
        title
      }}</a>
    </h1>
</template>
<script setup>
defineEmits(["titleClick"]);
</script>

App.vue

<template>
  <BlogPost v-for="blog in blogs" v-bind="blog" @titleClick="handleTitleClick">
    <button>分享到微信</button>
  </BlogPost>
</template>

<script setup>
function handleTitleClick(title) {
  console.log(title);
}
</script>

小结

好了,这个就是 Vue 的基础语法教程,你学会了吗?如果有帮助请三连并关注,想学更多的开发知识,可以在评论区留言,感谢观看!

Vue 3 完全入门教程

最新博客 

升级 Docusaurus 到 3.6,打包速度只需 5 秒钟

张旭乾
软件工程师 / B站UP主

这几天我把 Docusaurus 升级到了 3.6,主要是因为这个版本引入了 Rspack 和 SWC 等库,把打包速度提升了好几倍。以前打包大概要一两分钟,现在只需要五六秒就搞定了!

新的打包库, Rspadck, SWC, Lightning CSS

升级过程其实很简单,就是在 package.json 里把版本号改成最新的 3.6.1(当下最新版)。

CSS 动画完全指南

张旭乾
软件工程师 / B站UP主

随着现代网页设计的发展,CSS 动画已逐渐成为构建用户体验良好、互动性强的网站的关键。相比于静态的页面布局,动画能为用户带来更丰富的视觉体验,也能帮助网页更好地传达信息。

那么,为什么要用 CSS 动画呢?简单来说,CSS 动画可以通过视觉效果引导用户注意页面上的重要内容,例如按钮、链接、图标等,使用户的交互体验更加直观、自然。通过适当的动画设计,页面可以显得更具活力和吸引力,提高用户的留存率与参与度。

CSS 动画在网页中的应用也变得越来越重要。无论是加载动画、鼠标悬停效果,还是页面滚动时的动态内容展示,CSS 动画都能够轻松实现。再由于 CSS 动画轻量和高效的特性,我们可以在不影响页面性能的前提下,增强网站的互动性与用户体验。

这篇文章将详细介绍 CSS 动画的基础知识、关键技巧和常见应用,帮助初学者全面掌握 CSS 动画的使用方法,使大家能够轻松地为网页添加动态效果,提升网页开发和设计的专业性以及吸引力。

什么是CSS动画?

CSS 动画是通过定义一系列关键帧或过渡效果,使网页中的元素在指定时间内发生变化的一种技术。它能让网页元素平滑地改变属性,例如位置、大小、颜色、透明度等。

在现代网页设计中,CSS 动画有多种用途,常见的包括:

  • 加载动画:帮助用户了解页面正在加载,可以缓解因为等待而带来的焦虑感。
  • 交互效果:如按钮悬停、点击效果等,当用户与页面交互时,动画可以反馈出响应状态,提升用户的互动体验。
  • 滚动效果:在页面滚动时展示的动画内容,使得页面不再是静态的、单一的文本和图片,增加了视觉层次感。

10 个 CSS 1 行代码技巧

张旭乾
软件工程师 / B站UP主

在前端开发过程中,利用 CSS 一行代码技巧可以解决一些常见问题,提高编码效率,使样式设置更加简洁。本文将分享 10 个 CSS 一行代码技巧。

1. 居中对齐

居中对齐是 CSS 中的常见需求。通过一行 CSS 代码,可以实现元素的水平垂直居中。

display: grid; place-items: center;

12个 JavaScript 一行代码技巧

张旭乾
软件工程师 / B站UP主

JavaScript 是一种功能强大的编程语言,我们可以通过使用一行代码实现很多功能。在日常开发中,我们经常会遇到需要快速实现某些功能的情况。下面让我们一起看看 12个有用的 JavaScript 一行代码技巧。

1. 生成随机颜色

JavaScript 中可以通过以下方式快速生成一个随机颜色:

let randomColor = "#" + Math.floor(Math.random()*16777215).toString(16);

这行代码会生成一个六位的十六进制数,可以用作 CSS 颜色值。

2. 获取 URL 参数

如果你想获取 URL 参数,可以通过以下一行代码实现:

Vite 和 Webpack 的比较与区别

张旭乾
软件工程师 / B站UP主

前言

在现代前端开发中,打包工具已经成为不可或缺的一部分。它们可以将多个文件合并为一个或多个文件,使前端应用的加载和运行速度更快。目前,Vite 和 Webpack 是最受欢迎的打包工具之一。本文将介绍它们之间的比较和区别,以帮助你选择适合自己项目的工具。

什么是 Vite?

Vite 是一种新型的前端构建工具,旨在提高开发过程中的开发体验和构建速度。它支持所有的现代前端框架,如 Vue、React、Angular等,以及原生的 HTML/CSS/JS 应用。

Vite 的核心理念是“快速开发”。它采用了一种新的开发方式,即在开发过程中不需要事先打包应用程序,而是在应用程序运行时即时编译和构建。这种方式使得开发者可以更快地编写代码,而无需等待长时间的编译和构建过程。

什么是 Webpack?

Webpack 是一个广泛使用的打包工具,为现代 Web 应用程序提供了强大的静态资源管理功能。Webpack 可以将多个文件打包成一个或多个文件,并使它们在浏览器中快速加载。Webpack 是一个高度可配置的工具,因此可以根据项目的需要进行定制。

Webpack 的核心理念是“模块化”。它支持使用各种语言和框架编写模块,并将它们打包成可在浏览器中使用的 JavaScript 文件。Webpack 还提供了强大的插件系统,可以扩展其功能。

如何使用 JSX 编写 React 组件

张旭乾
软件工程师 / B站UP主

在 React 中,我们通常使用 JSX 来编写组件。JSX 是一种类似 HTML 的语法,它可以帮助我们更方便地编写组件,并且可以使代码更加易读和易于维护。在本文中,我们将介绍如何使用 JSX 编写 React 组件,并且将介绍 JSX 与 HTML 的区别、渲染列表、条件渲染、注册事件和传递 Props 相关知识。

React 框架简介

React 是一个由 Facebook 开发的用于构建用户界面的 JavaScript 库。它采用组件化的开发模式,使得开发者可以将一个 Web 应用程序拆分成多个组件,每个组件负责不同的功能,从而使得开发、测试和维护变得更加容易。

React 的主要特点是高效、可重用和灵活。它采用了 Virtual DOM 技术,可以最小化 DOM 操作,从而提高性能。另外,React 还拥有丰富的生态系统,包括 React Router、Redux、React Native 等等,可以帮助开发者更加高效地构建 Web 应用程序、移动应用程序和桌面应用程序等等。

10 种方法使用 CSS 水平居中一个元素

张旭乾
软件工程师 / B站UP主

我们在前端开发中,经常会有居中某个元素的需求。因为 CSS 对于居中的方式有多种多样,在不同场景下有不同的效果,需要特别记住它们的应用场景才能够正常的居中元素。那么这篇文章,我们就看一下在 CSS 中,水平居中一个元素的不同方法和技巧,帮助你在前端开发中更加游刃有余。

使用 text-align 居中行内元素

text-align 不仅可以居中文本,还可以居中行内元素(如文本或图片)。把父元素的 'text-align' 设置为 center,然后把子元素的 display 属性设置为 inline 就可以了。

.parent-element {
text-align: center;
}

配置 Vite alias 别名导入,避免冗长的相对路径

张旭乾
软件工程师 / B站UP主

在开发大型 Vue 项目的时候,有的组件会嵌套的很深,如果需要引入外层其他目录的组件,需要编写很长一段相对路径。假如有如下组件目录结构:

/Layout/Header/NavBar.vue
/Base/BaseLink.vue

如果在 NavBar 中引入 BaseLink 组件,需要使用下面的路径进行导入:

NavBar.vue
<script>
import BaseLink from '../../Base/BaseLink.vue';
</script>

这里使用了两个 ../ 才访问到 Base 目录,如果这个时候,我们给 ../../ 设置一个别名,例如 @,那么就可以使导入路径更简洁,变成:

@/Base/BaseLink.vue

Vite 支持设置路径别名,来支持这种形式的导入。

Vue3 表单提交事件处理

张旭乾
软件工程师 / B站UP主

这篇文章我们看一下对于表单整体的提交事件应该如何处理,并引入一个事件修饰符的概念。 我们继续使用上篇文章的项目示例,这里我把 html 中,class 为 form 的 div 改成了 form 元素,CSS 的样式也作了对应的调整。

<div class="form">
->
<form></form>
</div>

现在,我们在 form 元素的结束标签之前,添加一个 button 按钮元素,作为表单的提交按钮,点击它表单就会提交。

<textarea id="intro" rows="10" v-model="intro"></textarea>
<!-- 在这里添加 -->
<button type="submit">提交</button>

Vue 3 常见表单控件事件处理

张旭乾
软件工程师 / B站UP主

上篇文章我们学习了如何使用 v-model 绑定 input 输入框和 data 中的属性,这篇文章我们来看一下其它表单控件的绑定方法。

示例

这里示例大体的样式和结构我已经写好了,你可以从视频里附带的源代码示例里,直接编写代码。用户名这个我们上篇文章介绍了,这个就先不管它了。

单选按钮

我们先看一下单选框的数据绑定。假如我们让用户选择一下性别,男和女。我们在 HTML 模板中:

  • 定义一个 type 为 radio 的 input,name 设置为 gender,这里的 name 相同的 radio 单选框才能形成一个单选按钮组,这样选择是互斥的。
  • value 设置为 male,表示男性,这个是单选按钮选中之后,实际获取到的值。这里之所以用英文,是遵循了软件开发的一些最佳实践,方便后端程序或数据库,用枚举的形式存储数据,而枚举的属性名一般用英文。
  • 在 input 后面,我们用一个 span 元素显示给用户看的值,这里写上『男』。
  • 这里用 v-model 绑定一个名为 gender 的属性,这个我们稍后再在 data 里定义。