vite 快速上手
使用 vite 创建 vue3 项目
通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目。
| 1 | $ npm init vite-app <project-name> | 
或者 yarn:
| 1 | $ yarn create vite-app <project-name> | 
vue3.0入门
- setup()函数,接收两个参数,分别是 props,context,该函数是页面的入口函数,返回页面中用到的响应式数据
- ref用来声明一个响应式的普通值类型。包含:- string、number、Boolean、null、undefined等- 1 
 2
 3
 4
 5
 6
 7- import {ref} from "vue"; 
 setup(){
 const msg = ref("hello world")
 return{
 msg
 }
 }
- reactive用来声明响应式的引用类型。包含:- object、array等- 1 
 2
 3
 4
 5
 6
 7
 8
 9- import {reactive} from "vue"; 
 setup(){
 const msg = reactive({
 title:"Hello World"
 })
 return{
 msg
 }
 }
- onMounted页面加载时触发- 1 
 2
 3
 4
 5
 6
 7
 8- setup(){ 
 // 页面加载触发
 onMounted(() => {
 timer.value = setInterval(() => {
 data.counter++;
 }, 1000);
 });
 }
- onUnmounted页面销毁时触发- 1 
 2
 3
 4
 5
 6- setup(){ 
 // 页面销毁
 onUnmounted(() => {
 clearInterval(timer.value);
 });
 }
- computed计算属性,当数据更改时自定触发计算方法- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- setup(){ 
 // 当data.counter发生变化时,自动触发计算属性使 data.doubleCounter的值是data.counter的2倍
 const data = reactive({
 counter:1,
 doubleCounter: computed(() => data.counter * 2),
 });
 return{
 data
 }
 }
- toRefs将响应式对象转换为普通对象,在解构响应式的引用类型是不会丢失响应式- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- setup(){ 
 const state = reactive({
 foo:1,
 bar:2
 })
 // 如果不加toRefs,则解构后响应式会丢失
 const {foo,bar} = toRefs(state)
 return{
 foo,
 bar
 }
 }
- watch监听数据变化并触发方法- watch 函数接收两个参数
- 第一个参数时要监听的数据
- 第二个是一个函数,函数有两个参数,第一个参数是最新的值,* 第二个是修改前的值
- 监听的数据发生变化后执行函数里面的方法1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16setup(){ 
 const tagP = ref("");
 const counter = ref("")
 /*
 watch 函数接收两个参数
 第一个参数时要监听的数据
 第二个是一个函数,函数有两个参数,第一个参数是最新的值,第二个是修改前的值
 监听的数据发生变化后执行函数里面的方法
 */
 watch(counter, (newVal, oldVal) => {
 tagP.value.innerHTML = `from ${oldVal} to ${newVal}`;
 });
 return {
 tagP
 };
 }设置全局组件在 main.js 中引入设置的组件地址然后更改 createApp1 
 2import libComponent from "./view/libComponent.vue" 
 import libComponent2 from "./view/libComponent2.vue"然后在页面中使用1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13createApp(App) 
 // myDiv 是全局组件名称,h 是从vue中导出的函数
 .component("myDiv", {
 render: () => {
 return h(libComponent)
 }
 })
 .component("myDiv2", {
 render: () => {
 return h(libComponent2)
 }
 })
 .mount('#app')myDiv标签即可显示全局组件,声明多个公共组件时,写多个component即可
 
公共组件接收参数:组件页面利用props接收参数
| 1 | <template> | 
使用组件时传入参数
- myDiv已经声明成了全局组件,所以在页面中无需- components注册- 1 
 2- // myDiv 已经声明成了全局组件,所以在页面中无需 components 注册 
 <myDiv title="引入标题"></myDiv>
API 可做摇树优化
- vue2.0的- nextTick写法,挂载到了 Vue 上,无论用到与否,都会挂载到全局上,就会形成所谓的 dead code(死代码),这种 dead code 无法被 webpack 的 tree-shaking 排除掉。- 1 
 2
 3
 4
 5
 6
 7
 8
 9- import Vue from "vue" 
 export default {
 mounted(){
 Vue.nextTick(()=>{
 // code
 })
 }
 }
- 在 vue3.0 中做出相应优化,将他们抽离成为独立的函数,这样打包工具的摇树优化可以将这些 dead code 排除掉 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- import { nextTick } from "vue" 
 export default {
 setup(){
 nextTick(()=>{
 // code
 })
 }
 }
- 受影响的api - Vue.nextTick
- Vue.observable (Vue3.0中替换为 :reactive)
- Vue.version
- Vue.compile
- Vue.set
- Vue.delete
 
v-model 修饰符,子组件修改传入参数并实时响应
- vue3.0 中删除了 v-model和v-bind的sync修饰符,取而代之的是在v-model后加上参数来使用
首先在组件中接收父组件传递过来的参数,并且点击div使对参数进行修改,修改的数据做到子父组件双向绑定
| 1 | <template> | 
vue3.0的写法,直接在v-model后面跟上冒号和子组件接收的参数字段,并且传入一个初始数据
| 1 | <ModelTest v-model:conten="modelcounter"></ModelTest> | 
注意:如果v-model后没有参数时,在子组件内部接收的参数名为默认值:modelValue
举例如下:
父组件
| 1 | <ModelTest v-model="counter"></ModelTest> | 
子组件
| 1 | <template> | 
vue2.0的写法,需要手动添加 update:conten 方法,并且在方法内编写数据修改逻辑
| 1 | <template> | 
渲染函数 render 以及插槽 slot 的基本使用方法
vue3.0中 render 函数不在接收 h 函数,改用手动导入 h 的方式,使用 components 注册一个自定义组件,使用render 渲染自定义组件内容,setup 函数返回的数据会挂载到 ctx 参数上,render 函数接收一个 ctx 参数,render 返回一个 h 函数,h 函数声明自定义组件的内容以及逻辑。
- h 函数接收三个参数- 第一个参数是元素标签
- 第二个参数时元素的属性以及元素方法
- 第三个参数时元素的值
 
| 1 | components: { | 
setup 的第二个参数可以解构为 emit slots attrs
自定义完组件后再dem中使用,并且给自定义组件传递参数。同时利用插槽插入元素
| 1 | <template> | 
函数式组件的声明方式(不推荐,仅了解),推荐使用状态组件
首先创建 Functional.vue ,编写如下代码
| 1 | <script> | 
接着在页面中注册并传递参数
| 1 | <!-- 函数式组件的声明方式 --> | 
defineAsyncComponent 异步加载组件
声明异步组件时用 defineAsyncComponent 函数包起来,和函数式组件区分开来
| 1 | <template> | 
使用 directive 自定义指令
- 使用 directive函数自定义指令,directive接收两个参数,分别如下:- 第一个参数声明指令名称,在使用时前面要加上 v-
- 第二个参数是一个对象,里面添加指令的触发时机,具体如下:- created: 元素创建时
- beforeMount: 元素插入视图之前
- mounted: 元素插入视图之后
- beforeUpdate: 元素更新之前
- updated: 元素插入视图之后
- beforeUnmount: 元素销毁前
- unmounted: 元素销毁后
 
 
- 第一个参数声明指令名称,在使用时前面要加上 
- 每个声明周期函数都有三个参数,el(元素本身)、binding(自定义指令等于的值)、vnode(虚拟dom描述),具体使用方法:*
在 main.js 中的 createApp(App) 方法后链式调用 directive 方法,编写自定义指令,bgColor 为自定义指令名称
方式一:链式调用
| 1 | createApp(App) | 
方式二:分开调用
| 1 | let app = createApp(App) | 
在全局中采用 v-<createName>='xxx' 的方式使用
| 1 | <template> | 
也可以在单个组件中设置自定义指令
| 1 | export default { | 
在组件内部使用
| 1 | <template> | 
vueCompilerOptions 设置自定义组件白名单
有时候利用 render 函数自定义渲染容器时声明了一些自定义组件名,页面中可以正常使用,但是控制台会报一些警告信息,此时在 vite.config.js 文件中使用 vueCompilerOptions 声明自定义组件白名单。
| 1 | module.exports = { | 
设置完毕后重新启动便不再有警告信息。
transition类名变更
vue3.0 中的 transition 动画类型发生了一些变化,更加语义化
- v-enter → v-enter-from
- v-leave → v-leave-from
完整示例:点击按钮控制元素隐藏和显示,同时显示过度动画
| 1 | <template> | 
keyCode 作为 v-on 修饰符被移除
vue3.0中的keyCode作为修饰符被移除,改用具体的按键名代替
| 1 | <!-- vue3.0写法 --> | 
| 1 | import { ref } from "vue" | 
使用 mitt 完成事件派发和监听
- 首先安装 mitt - 1 - npm intall mitt -D 
- 安装完成后在 util -> mitt.js 文件中进行初始化并导出 - 1 
 2
 3
 4- import mitt from "mitt" 
 const emitter = mitt();
 export default emitter
- 使用 emitter.emit() 完成事件的派发 - 1 
 2
 3- import emitter from "../util/mitt.js"; 
 emitter.emit("helloPageEmitFun", inputText.value);
- 使用 emitter.on() 监听事件 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- import emitter from "../util/mitt.js"; 
 import { onMounted } from "vue";
 export default {
 setup() {
 // 页面挂载完毕后监听事件
 onMounted(() => {
 // 监听事件,接收参数并触发
 emitter.on("helloPageEmitFun", (value) => {
 console.log(value);
 });
 });
 },
 };
- 使用 emitter.off() 关闭事件监听 
首先将监听触发的事件封装成一个单独的函数
| 1 | <button @click="unsubHandler">关闭事件监听 | 
| 1 | import emitter from "../util/mitt.js"; | 
vue3 中如何引如 router,以及 vue-router 4 的用法
首先安装 router
| 1 | npm install vue-router@next | 
在 App.vue 文件中添加 router-view 标签
| 1 | <template> | 
新建 router -> index.js 文件,初始化如下,主要变化有两点,应该从 vue-router 中导出 createRouter 和 createWebHashhistory ,并且将 router 作为一个实例导出
| 1 | import { createRouter, createWebHashHistory } from "vue-router" | 
在 main.js 文件中导入并使用,使用方法就是直接在 createApp 方法后面继续调用 use 方法,传入router 实例
| 1 | import router from "./router/index" | 
最后在页面中完成使用
| 1 | <ul> | 
vue3.0 中 router 的一些新特性
1. router.addRoute()添加路由
在 router -> index.js 文件中,导出 router 之前,可以使用router.addRoute()来添加路由,该函数接收两个参数,第一个参数是父页面的name,第二参数是路由,第一个参数可以不写
不声明父页面
| 1 | router.addRoute({ | 
页面路径: http://localhost:3000/#/about
声明父页面
| 1 | router.addRoute("home",{ | 
页面路径: http://localhost:3000/#/home/about
2. 点击按钮完成页面跳转
页面跳转并传递参数
| 1 | // 从 vue-router 中导出 useRouter | 
子页面接收路由参数
- 从 vue-touter 中导出 useRoute,注意要和 useRouter 区分开1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11// 从 vue-touter 中导出 useRoute 
 import { useRoute } from "vue-router";
 export default {
 setup() {
 // 获取路由实例
 const route = useRoute();
 // 获取路由参数
 console.log(route.query);
 },
 };
3. 页面离开之前和路由参数更新后触发函数
| 1 | import { onBeforeRouteLeave, onBeforeRouteUpdate } from "vue-router"; | 
router4.0 中的一些变化 (一)
1.实例创建方式, history 选项替代了 mode 选项,取而代之的是:
- createWebHashHistory() 路径后面会携带 #
- createMemoryHistory() 服务端渲染用
- createWebHistory() 路径后面不会携带 # ,便于摇树优化掉无用的 history
- base选项移至createWebHashHistory()等方法中作为参数使用1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11const router = createRouter({ 
 // 加上参数后可以在所有路径前增加前缀
 history: createWebHistory("/addUrl"),
 routes: [
 {
 path: "/",
 name: "home",
 component: Home,
 },
 ]
 })
2.通配符 * 被移除,导航到404页面,使用正则匹配路径,当所有页面匹配不成功时进入404页面
| 1 | const router = createRouter({ | 
3.页面跳转完后触发 router.isReady(),触发时机在 onMounted 之后
| 1 | // 页面跳转完后触发 | 
4.scrollBehavior变化,第三个参数记录页面的滚动位置,页面跳转在返回时会重新回到上次的滚动位置。
- vue2.0 中第三个参数的返回值为 { x:10 , y:10 }
- vue3.0 中第三个参数的返回值为 { left:10 , top:10 }1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21const router = createRouter({ 
 // 加上参数后可以在所有路径前增加前缀
 history: createWebHistory("/addUrl"),
 routes: [
 {
 // ........
 }
 ],
 // 页面跳转页面再返回是,重新回到上次的滚动位置
 scrollBehavior(to, from, position) {
 console.log(position, "页面位置信息");
 if (position) {
 return position;
 } else {
 return {
 top: 0,
 left: 0
 }
 }
 }
 })router4.0 中的一些变化 (二)1.keep-alive 必须写在 vouter-view 标签内部。
- keep-alive 是作用是缓存组件,例如,商品列表进入详情页时,在返回还是保持上次查询结果1 
 2
 3
 4
 5<router-view v-slot="{Component}"> 
 <keep-alive>
 <component :is="Component"/>
 </keep-alive>
 </router-view>
2.router-link 标签上删除了 tag、event属性,改用如下方式替代,使用插槽的方式,可以自定义跳转的样式,替代默认的a标签
| 1 | <router-link to="/" v-slot="{ navigate }" custom> | 
vue3.0中使用vuex
首先安装 vuex4.0 版本
| 1 | npm install vuex@next | 
新建 store -> index.js 文件,初始化代码如下
代码中有两个存储数据 count 和 userName,以及两个方法,addCount(接收参数追加count),setUserName(接收到一个新的名称改变全局存储的userName)
| 1 | // 从 vuex 中导出 createStore 函数 | 
在 main.js 文件中引入 store/index.js 文件,并挂载到 vue 全局中
| 1 | import store from "./store/index" | 
在页面中使用
| 1 | <!-- 使用vuex --> | 
| 1 | // 从 vuex 中导出 useStore 函数 | 
代码规范和格式化 eslint + prettier 规范代码
我们借助eslint规范项目代码,通过prettier做代码格式化。
首先在项目安装如下依赖,在 package.json 文件夹下
| 1 | { | 
接着在项目根目录添加 .eslintrc.js 文件,进行如下配置
| 1 | module.exports = { | 
然后继续在根目录添加 prettier.config.js 文件,内容如下
| 1 | module.exports = { | 
然后 npm install 安装一下新增的依赖,安装成功后重启项目。打开任意文件,格式化之后查看配置项是否生效,运行 npm run lint 检查错误项
测试环境
利用jest和@vue/test-utils测试组件
安装依赖
| 1 | "jest": "^24.0.0", | 
配置 babel.config.js
| 1 | module.exports = { | 
配置 jest.config.js
| 1 | module.exports = { | 
设置启动命令
| 1 | "test": "jest --runInBand" | 
新建测试代码 tests/example.spec.js
| 1 | import HelloWorld from "main/components/HelloWorld.vue"; | 
lint配置添加jest环境,要不然会有错误提示:
| 1 | module.exports = { | 
将lint、test和git挂钩
| 1 | npm i lint-staged yorkie -D | 
| 1 | "gitHooks": { | 
使用ts
vite可直接导入 .ts 文件,在 script 标签中通过 <script lang="ts"> 使用
范例
| 1 | <template> | 
此外,还应该在 package.json 中声明 ts 的版本 
| 1 | "devDependencies": { | 
然后在根目录新建 tsconfig.json 文件作为 ts 的配置文件
| 1 | { | 
vite 项目配置
首先应该在根目录新建 vite.config.js
1. 给导入文件的路径起别名
起别名可以避免出现大量的嵌套导入
vite.config.js 文件中配置如下信息
| 1 | const path = require("path") | 
配置完之后重启项目
在页面中使用
| 1 | // 使用具体地址导入 | 
2. 设置代理
| 1 | export default { | 
使用
| 1 | fetch("/api/users") | 
扩展: fetch 理解
- fetch是全局量window的一个方法,第一个参数为URL。
- url参数是必须要填写的,option可选,设置fetch调用时的Request对象,如method、headers等- method - 支持 GET, POST, PUT, DELETE, HEAD
- url - 请求的 URL
- headers - 对应的 Headers 对象
- body - 请求参数(JSON.stringify 过的字符串或’name=jim\u0026age=22’ 格式)
 
- fetch()方法与XMLHttpRequest类似,fetch也可以发起ajax请求,但是与XMLHttpRequest不同的是,fetch方式使用Promise,相比较XMLHttpRequest更加的简洁。
- fetch方法的then会接收一个Response实例,值得注意的是fetch方法的第二个then接收的才是后台传过来的真正的数据,一般第一个then对数据进行处理等。
post 请求方法
| 1 | fetch("/users.json", { | 
get 请求方法
| 1 | fetch("/api/users") | 
3. 数据mock
安装依赖
| 1 | npm i mockjs -S | 
引入插件,vite.config.js
| 1 | plugins: [ | 
需要注意一点,使用mock时要设置环境变量 package.json,否则运行不起来 mock
| 1 | "dev": "cross-env NODE_ENV=development vite" | 
创建 mock 文件,mock/test.js
| 1 | export default [ | 








