Vue3、Vue2都有哪些区别

news2025/7/4 18:38:20

vue3和vue2版本对比:

vue2中绝大多数的API与特性,在vue3中同样支持。同时,vue3中还新增了所特有的功能,并废弃了vue2中的某些旧功能。

新增的功能如:组合式API、多根节点组件、更好的TypeScript支持等。

废弃的功能如:过滤器、不在支持$on,$off,$once等实例方法。

详细变更信息可参考官方文档的迁徙指南:https://v3.vuejs.org/guide/migration/introduction.html

vue3和vue2中过滤器:

过滤器仅在vue2和vue1中支持,在vue3中剔除了过滤器的使用,在vue3中官方建议使用计算属性或方法代替剔除的过滤器功能。

SPA(单页面应用程序)优点:

1.良好的交互体验

①单页面应用内容的改变不需要重新加载整个页面

②获取数据也是通过Ajsx异步获取

③没有页面之间的跳转,不会出现白屏现象

2.良好的前后端工作分离模式

①后端专注于提供API接口,更易于实现API接口复用

②前端专注于页面的渲染,更利于前端的工程化发展

3.减轻服务器的压力

①服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高数倍

SPA(单页面应用程序)缺点与解决办法:

1.首屏加载慢

①路由懒加载

②代码压缩

③CDN加速

④网络传输压缩

2.不利于SEO

①SSR服务器端渲染

如何快速创建vue中的SPA(单页面应用程序)项目:

1.基于vite创建

2.基于vue-cli创建

vite创建的四部曲:

1.npm init vite-app 项目名称

2.cd 项目名称

3.npm i

4.npm run dev

vue2、vue3 <template>中的节点数不同:

vue2中,<template>节点内仅支持单个根节点

<template>
  <div>
    <h1>根组件</h1>
    <p>p标签</p>
  </div>
</template>

vue3中,<template>节点内支持多个根节点

<template>
  <div>
    <h1>根组件</h1> 
  </div>
  <p>p标签</p>
  <div>div标签</div>
</template>

vue3中组件的注册分为两种:

1.全局组件,可以在全局任何一个组件内使用

main.js全局注册,可以在任何其他组件内使用

​// 导入createApp函数
import { createApp } from 'vue'
// 导入待渲染的根组件
import App from './App.vue'
import './index.css'
// 导入需要被全局注册的组件
import Left from "./components/left1.vue"
// console.log(Left.name);Left1
// 调用createApp函数,创建spa应用的实例
const app=createApp(App)
// 调用app.component方法全局注册组件
app.component("My-Left",Left)
// 此处注册的全局注册组件,也可替换为
// app.component("Left.name",Left)

app.mount('#app')

​

2.局部组件,只能在当前注册的范围内使用

<template>
  <div>
    <My-Left></My-Left>
    <h1>根组件</h1>
    <My-Search></My-Search>
  </div>
</template>

<script>
import Seach from "./components/seach.vue";
export default {
  name: "App",
  components: {
    // 注册私有组件
    "My-Search": Seach,
  },
};
</script>

定义组件名称的两种方式:

1.使用kebab-case命名法(俗称短横线命名法,如:my-left)

特点:严格按照短横线名称进行使用

2.使用PascalCase命名法(俗称帕斯卡命名法或大驼峰命名法,如:MyLeft)

特点:既可以按照帕斯卡使用,又可以转化为短横线使用(适用性强,推荐使用)

样式穿透/deep/:

如果给当前组件的style节点添加了scoped属性,则当前组件的样式对子组件是不生效的。如果想让某些样式对子组件生效,可以使用/deep/深度选择器。

注:/deep/是在vue2中的写法,vue3推荐使用:deep()

<style lang="less" scoped>
/* vue2写法 */
/deep/.change {
  color: red;
}
</style>
<style lang="less" scoped>
/* vue3写法 */
:deep(.change ){
  color: red;
}
</style>

class与style绑定的几种方式:

<template>
  <div>
    <!-- 数组形式的绑定 -->
    <!-- <h1 :class="[fontIs ? 'ac' : '', del ? 'delete' : '']">根组件</h1>
     <button @click="fontIs = !fontIs">缩放</button>
    <button @click="del = !del">删除切换</button>
     -->
    <!-- 对象形式的绑定,简化数组形式的臃肿问题 -->
    <!-- <h1 :class="obj">根组件</h1>
    <button @click="obj.ac = !obj.ac">缩放</button>
    <button @click="obj.delete = !obj.delete">删除切换</button> -->

    <hr />
    <!-- 以对象的语法绑定内联style样式,注:fontSize不以驼峰的方式引用,就要采用字符串的方式使用 -->
    <div
      :style="{ color: active, fontSize: size + 'px', 'background-color': bgc }"
    >
      相信光
    </div>
    <button @click="size++">字体变大</button>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      // fontIs: true,
      // del: true,
      obj: {
        ac: true,
        delete: true,
      },
      active: "red",
      size: 30,
      bgc: "pink",
    };
  },
};
</script>
<style  scoped>
.ac {
  font-size: 40px;
}
.delete {
  text-decoration: line-through;
}
</style>

props的自定义验证函数:

 props: {
    type: {
      // 通过 validator函数对属性值进项校验,参数通过value进行接收
      // 如果没有下面的值,控制台会警告
      validator(value) {
        return ["sucess", "reject", "resolve"].indexOf(value) != -1;
      },
    },
  },

computed和methods细节区别:

<h1>{{ blus }}</h1>
  <h1>{{ plus() }}</h1>

computed: {
    // 调用不用加()
    blus() {
      return this.count * 3;
    },
  },
  methods: {
    // 调用要加()
    plus() {
      return this.count * 3;
    },
  },

vue3中组件的自定义事件:

为了让组件的使用者可以监听到组件内状态的变化,此时需要用到组件的自定义事件。

自定义事件的三个使用步骤

封装组件时:

①声明自定义事件(必须在emits节点中声明)

②触发自定义事件(通过this.$emit(“自定义事件名称”)进行触发)

使用组件时:(v-on或@进行监听)

③监听自定义事件

例:

子组件child.vue

<template>
  <div>
    child组件的count值是:{{ count }}
    <button @click="add">+1</button>
  </div>
</template>
<script>
export default {
  name: "MyChild",
  // 1.声明自定义事件
  emits: ["countChange"],
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    add() {
      this.count++;
      //2. 触发自定义事件,可以传递第二个参数为自定义事件传参
      this.$emit("countChange", this.count);
    },
  },
};
</script>

根组件App.vue

<template>
  <div>
    根组件
    <hr />
    <MyChild @countChange="getCount"></MyChild>
  </div>
</template>

<script>
import MyChild from "./components/props/child.vue";
export default {
  name: "App",
  components: {
    MyChild,
  },
  methods: {
    getCount(value) {
      console.log("触发了自定义事件" + value);
    },
  },
};
</script>

vue3的组件中v-model(实现组件的内外同步)子向父传值的不同之处:

根组件:

<template>
  <div>
    <h1>根组件---{{ count }}</h1>
    <button @click="count++">+1</button>
    <!-- 1.在v-bind之前添加v-model指令 -->
    <MyChild v-model:num="count"></MyChild>
  </div>
</template>
<script>
import MyChild from "./components/props/child.vue";
export default {
  name: "App",
  data() {
    return {
      count: 0,
    };
  },
  components: {
    MyChild,
  },
};
</script>

子组件:

<template>
  <div>
    child组件 {{ num }}
    <button @click="add">+1</button>
  </div>
</template>
<script>
export default {
  name: "MyChild",
  props: ["num"],
  // 2.子组件声明emits自定义事件,格式为update:
  emits: ["update:num"],
  methods: {
    add() {
      // 3.调用$emit触发自定义事件,更新父组件中的数据
      // 旧值+1后通过"update:num"更新到父组件中
      this.$emit("update:num", this.num + 1);
    },
  },
};
</script>

组件的生命周期:

指的是组件从创建->运行->销毁的整个过程,强调的是一个时间段。

vue框架为组件内置了不同时刻的生命周期函数,生命周期函数会随着组件的运行而自动调用。如:①当组件在内存中被创建完毕之后,会自动调用created函数

②当组件被成功的渲染到页面上之后,会自动调用mounted函数

③当组件被销毁完毕之后,会自动调用unmounted函数

vue3中主要的生命周期函数:

 vue3中全部的生命周期函数:

 vue3中的数据共享:

vue3中子向父传值要使用$emits声明一个自定义事件

兄弟之间传值eventBus:

安装mitt依赖包,执行如下命令

npm install mitt@2.1 -S

eventBus.js文件

// 导入mitt包
import mitt from "mitt"
// 创建实例对象
const bus=mitt()
// 共享出去
export default bus
<template>
  <div>
    数据发送方count的值为{{ count }}
    <button @click="add">+1</button>
  </div>
</template>
<script>
import bus from "../eventBus.js";
export default {
  name: "MyLeft",
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    add() {
      this.count++;
      bus.emit("countChange", this.count);
    },
  },
};
</script>
<template>
  <div>数据接收方num的值为{{ num }}</div>
</template>
<script>
import bus from "../eventBus.js";
export default {
  name: "MyRight",
  data() {
    return {
      num: 0,
    };
  },
  created() {
    bus.on("countChange", (count) => {
      this.num = count;
    });
  },
};
</script>
<template>
  <div>
    根组件
    <Right></Right>
    <Left></Left>
  </div>
</template>
<script>
import Right from "./components/props/right.vue";
import Left from "./components/props/left.vue";

export default {
  name: "App",
  data() {
    return {};
  },
  components: {
    Right,
    Left,
  },
};
</script>

后代关系组件之间的数据共享:

后代关系组件之间的数据共享数据,指的是父节点组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,可以使用provide(共享时使用)inject(接受时使用)实现后代关系组件之间的数据共享。(注:没有直接或间接关系是无法使用的)

<template>
  <div>
    根组件{{ color }}
    <button @click="color = 'red'">切换</button>
    <Left></Left>
  </div>
</template>
<script>
import Left from "./components/left.vue";
// 按需导入计算属性
import { computed } from "vue";
export default {
  // name: "App",
  data() {
    return {
      color: "orange",
    };
  },

  components: {
    Left,
  },
  provide() {
    // 返回共享出去的数据对象,非响应式的
    // return { color: this.color };
    // 利用computed函数向下共享响应式的数据。
    return {
      color: computed(() => this.color),
    };
  },
};
</script>
<template>
  <div>
    二级组件{{ color.value }}
    <Right></Right>
  </div>
</template>
<script>
import Right from "./right.vue";
export default {
  inject: ["color"],
  components: {
    Right,
  },
};
</script>
<template>
  <!-- 如果父级共享的是响应式数据,则子孙节点需要以.value的形式使用 -->
  <div>三级组件{{ color.value }}</div>
</template>
<script>
export default {
  inject: ["color"],
};
</script>

数据共享的六种方法:

1.父子关系

①父->子  属性绑定

②子->父  事件绑定

③父<->子 组件上的v-model

2.兄弟关系

①eventBus

3.后代关系

①provide&&inject

4.全局数据共享

①vuex

vue3中全局配置axios

自定义指令:

vue2中使用的是{bind,update},vue3中使用的是{mounted,updated}

路由:

Vue-router目前有3.x和4.x版本的,vue3使用4.x版本的,vue2使用3.x版本的。

版本3和版本4路由的最主要的区别:创建路由模块的方式不同。

vue3中路由的基本使用步骤:

①在项目中安装vue-router(npm install vue-router@next -S)

②定义路由组件

③声明路由链接(<router-link></router-link>)和占位符(<router-view></router-view>)

<div>
    <router-link to="/left">左导航</router-link>&nbsp;
    <router-link to="/right">右导航</router-link>
    <router-view></router-view>
  </div>

④创建路由模块

// 按需导入两个方法 分别是创建路由的实例对象和指定路由工作模式
import {createRouter,createWebHashHistory} from "vue-router"
import Left from "./left.vue"
import Right from "./right.vue"
const router=createRouter({
  // 指定路由工作模式,以哈希进行组件的切换
history:createWebHashHistory(),
routes: [
  {path:"/left", component:Left},
  {path:"/right", component:Right},
]
})

export default router

⑤导入并挂载路由模块

//在main.js导入路由
import router from "./components/router.js"
// 挂载路由模块
app.use(router)

激活路由链接高亮的两种方式:

①使用默认的高亮class类

/* 被激活的路由链接中,默认会有一个叫做router-link-active的类名,可用此类名为路由链接设置高亮模式 */
.router-link-active {
  background-color: aqua;
  color: white;
  font-weight: bolder;
}

②自定义路由高亮的class类

//在router.js里面修改
const router=createRouter({
  // 指定路由工作模式,以哈希进行组件的切换
history:createWebHashHistory(),
// 默认的router-link-active类名会被覆盖掉
linkActiveClass:"change",
routes: [
  {path:"/left", component:Left},
  {path:"/right", component:Right},
]
})

命名路由:

通过name属性为路由规则定义名称的方式,叫做命名路由。命名路由的name值不能重复,必须保证唯一性。

 //命名路由

{ name:"move",path:"/left", component:Left},

使用命名路由实现声明式导航

为<router-link>标签动态绑定to属性的值,并通过name属性指定要跳转到的路由规则。期间还可以用params属性指定跳转期间要携带的路由参数。

<router-link :to="{name:'move',params:{id:3} }">go to</router-link>

使用命名路由实现编程式导航

调用push函数期间指定一个配置对象,name是要跳转到的路由规则,params是携带的路由参数

​
<template>
<button @click="goto(3)">go to</button>
</template>
<script>
export default {
methods:{
goto(id){
this.$router.puah({name:"move",params:{mid:id}})
}
}
}
</script>

​

导航守卫:

其中next参数调用的三种方式

①next()直接调用,直接放行

②next(false)强制停留在当前页面

③next(“/login”)强制跳转到登录页面​​​​​

vue-cli:

安装vue-cli

​​​​​​​npm install -g @vue/cli

yarn global add @vue/cli 

创建项目的两种方式

1.基于命令行的方式创建vue项目

vue create 项目名称

2.基于可视化面板创建vue项目

vue ui 

基于vue ui 创建项目的步骤

1.在vue ui文件下打开PowerShell 输入vue ui命令并回车,此时会跳到创建项目的面板(注:不要关闭PowerShell)

2.点击创建,并点击下面的在此创建新项目

3.输入项目名称(如:vue-ui-number1)

4.点击下一步进入到预设面板,选择手动,进入功能面板

5.功能面板只勾选Babel、CSS Pre-processors和使用配置文件,并点击下一步

6.根据自己的需求选择vue版本和预处理器(在这:我们选择2x和less预处理器),然后点击创建项目

7.需要保存 输入预设名并点击保存预设名创建项目(在.vuerc下可以清除预设)

vue组件库:

在实际开发中,前端开发者可以把自己封装的.vue组件整理打包,并发布为npm的包,从而供其他人下载和使用。这种可以直接下载并在项目中使用的组件,就叫vue组件库。

vue组件库和bootstrap的区别

bootstrap只提供了纯粹的原材料(css样式,html结构以及js特效),需要由开发者做进一步的组装和改造

vue组件库是遵循vue语法,高度定制的现成组件,开箱即用

最常用组件库:

1.pc端

①Element UI(支持vue2(使用旧版)和vue3(使用新版)使用)

②View UI

2.移动端

Mint UI和Vant

axios拦截器在vue2和vue3中的配置有所不同

拦截器会在每次发起ajax请求和得到响应的时候会自动被触发,主要应用如:token身份认证,loading效果等。

配置请求拦截器:

通过axios.interceptors.request.use(成功的回调,失败的回调)可以配置请求拦截器,失败的回调可以被省略。

proxy跨域代理:

通过vue-cli创建的项目在遇到接口跨域问题时,可以通过代理的方式来解决。

1.在main.js文件中,把axios的请求根路径改为当前vue项目运行地址(请求接口不在跨域)

2.在项目根目录下创建vue.config.js的配置文件,并声明如下配置后重新运行项目。

module.export={

devServer:{
//仅在开发阶段的项目生效,会将任何未知请求(没有匹配到静态资源文件的请求)代理到
相应的地址
//项目上线发布时,依旧需要API接口服务器开启CROS跨域资源共享
proxy:"后台地址路径"
}


}

更多其他内容,请参考官方文档!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/407577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jq获取和设置标签的css样式、jq给标签增加或移除class属性

1、jQuery获取和设置标签的css样式 jQuery既可以直接获取标签的css样式&#xff0c;也可以设置样式&#xff0c;包括行内、内部、外部样式&#xff1b;思路&#xff1a;先要选取这个标签&#xff0c;然后再获取或者设置样式&#xff1b;获取css属性&#xff1a;console.log($…

eclipse新建一个简单的网站(web)项目

目录前言一、新建一个简单web项目二、报错解决前言 本篇介绍怎么在eclipse中新建一个简单的web项目&#xff0c;博主是用的eclipse版本是2021-06R&#xff0c;服务器tomcat10。本篇是博主尝试自己动手搭建网站系列文章中的一篇&#xff0c;如想了解更多相关内容&#xff0c;见…

在web页面中直接播放rtsp视频流

rtsp是一种实时传输协议&#xff0c;通过各种百度了解&#xff0c;得出结论&#xff1a;浏览器是不支持播放rtsp流的&#xff0c;必须经过后端转码推流。 实现思路&#xff1a;借助node搭建转码推流服务&#xff0c;再使用JSMpeg播放。 rtsp2web是一个依赖 ffmpeg&#xff0c…

Vue页面生成PDF的方法

最近项目有个需求&#xff0c;将系统统计的数据生成分析报告&#xff0c;然后可以导出成PDF。 这种方法可以有两种&#xff0c;一种是直接调用打印&#xff0c;用户通过浏览器提供的打印页面手动选择导出PDF。当然这种方式兼容性差&#xff0c;且体验不好&#xff0c;显然不是…

net::ERR_CONNECTION_REFUSED 解决大全

sockjs-node/info报错 GET http://localhost/sockjs-node/info?t1641268443660 net::ERR_CONNECTION_REFUSED sockjs-node作用 SockJS is a JavaScript library (for browsers) that provides a WebSocket-like object. SockJS gives you a coherent, cross-browser, Javascr…

前端页面出现 Failed to load response data

工作上前端 搭建了一套新的环境 同一个接口 新的前端环境 调用接口时 偶尔会出现一个情况 这时候 我们 在服务器 、 Postman 、本地环境调用都没问题 唯独在新的前端页面上会出现这样的问题 鉴于这样的问题 在网上查询了很多方法 进行修正都无济于事 最终在我们将问题指向了…

Android基础入门

第1章 Android基础入门 目录第1章 Android基础入门1.1 Android简介1.1.1 通信技术1.1.2 Android发展史1.1.3 Android体系结构1.1.4 Dalvik虚拟机1.2 Android开发环境搭建1.2.1 Android Studio安装1.2.2 模拟器创建1.2.3 SDK下载1.3 Android程序结构1.4 资源的管理与使用1.4.1 图…

前端第二章:9.HTML如何在网页中添加图片(img标签使用方法,以及img标签属性:alt、height、width);图片格式选择

一、img 标签简介 1.是自结束标签 2.用于向当前页面引入一个 外部图片 3.可以引入 gif 动图 4.img 是 替换元素&#xff0c;具有块元素和行内元素的某些特点 二、img标签基础 0.使用img标签将 图片 引入 网页&#xff01; 1.代码&#xff1a; <img src"图片的相对路…

【前端项目问题】Vue 中 v-html 的使用

Vue 中 v-html 的使用一、 v-html是什么&#xff1f;二、使用方式一、 v-html是什么&#xff1f; v-html 用来更新元素的 innerHTML&#xff0c;但是存在一定的安全性。 注意&#xff1a; 1、内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。 2、在网站上动态渲染任意 HTM…

前端技术发展历程

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 随着互联网的不断发展…

了解SVG-icon的使用流程

一.了解SVG是什么 SVG&#xff08;Scalable Vector Graphics&#xff09;可缩放矢量图形&#xff0c;是一种用于描述基于二维的矢量图形的 XML 标记语言&#xff0c;其基本矢量显示对象包括矩形、圆、椭圆、多边形、直线、任意曲线等&#xff0c;还能显示文字对象和嵌入式外部…

使用elementUI组件实现表格的分页以及搜索功能

主要的UI组件&#xff1a;el-input、el-table、el-pagination 效果展示&#xff1a; 主要功能&#xff1a; ① 完成列表与分页组件的联动&#xff0c;可以通过分页来实现列表数据翻页。 ② 通过在搜索栏输入关键词&#xff0c;在列表中展示出与关键词有关数据。 基础设置&a…

微信小程序实现滑动/点击切换Tab

背景 &#x1f44f; swiperscroll-view实现滑动/点击切换Tab&#xff0c;以及scroll-left的使用~ &#x1f947;文末分享源代码。记得点赞关注收藏&#xff01; 1.实现效果 2.实现步骤 2.1 scroll-view实现tab列表 scroll-view&#xff1a; 可滚动视图区域。使用竖向滚动时…

jsPDF + html2canvas A4分页截断 完美解决方案(含代码 + 案例)

业务需求 网页html生成A4大小分页的pdf&#xff0c;翻遍了整个互联网发现没有很系统的整理与分析&#xff0c;甚至对jsPDF的解析也没有几篇。遇到过几次&#xff0c;用的比较多&#xff0c;完成代码编写后特此整理分析&#xff0c;自我记录。 业务难点 1.存在图片/组件/文字…

vue弹窗如何嵌入其它vue页面

文章目录说明子组件&#xff0c;将要引入到弹框内的页面父页面思考组件 v-if 和 v-show 切换时生命周期钩子的执行说明 【1】实现方式&#xff0c;将其他页面作为组件传入 【2】在父页面&#xff0c;将该组件引入到弹框内&#xff0c;并通过动态渲染进行切换 子组件&#xff0…

使用宝塔面板快速搭建web网站,并内网穿透实现公网远程访问

目录 1. 环境安装 2. 安装cpolar内网穿透 3. 内网穿透 4. 固定http地址 5. 配置二级子域名 6. 创建一个测试页面 宝塔面板简单几步搭建本地web站点&#xff0c;并做内网穿透&#xff0c;实现公网用户也可以正常远程访问&#xff0c;无需公网IP&#xff0c;无需设置路由器…

echarts入门基础教程

目录 效果图 1.下载资源 新建项目 2.引入echarts 3.准备一个呈现图表的盒子 4.初始化echarts实例对象 5.准备配置项 6.将配置项设置给echarts实例对象 7.完整代码 效果图 1.下载资源 新建项目 去官网下载echarts压缩包&#xff0c;在包里的dist文件里找到echarts.min.j…

使用vite构建Vue3组件库,发布npm包

使用vite构建Vue3组件库&#xff0c;发布npm包 在国内用vue框架开发的是非常之多的&#xff0c;使用vue开发组件封装是一个很普片的事情了&#xff0c;封装好一个组件可以在项目的任意地方去使用&#xff0c;我们还可以从npm仓库下载别人封装的组件进行使用&#xff0c;比如ele…

基于Java+Springboot+vue高校资源共享交流平台设计和实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【完整代码】用HTML/CSS制作一个美观的个人简介网页

【完整代码】用HTML/CSS制作一个美观的个人简介网页整体结构完整代码用HTML/CSS制作一个美观的个人简介网页——学习周记1HELLO&#xff01;大家好&#xff0c;由于《用HTML/CSS制作一个美观的个人简介网页》这篇笔记有幸被很多伙伴关注&#xff0c;于是特意去找了之前写的完整…