目录
一、创建项目
二、SFC 语法规范
三、模板与语法
模板
语法
1、v-text:用来显示文本
2、v-html:用来展示文本、标签,但不支持组件
3、v-if :用来控制元素的显示隐藏(切换真假DOM)
v-else-if :表示 v-if 的“else if 块”。可以链式调用
v-else :v-if条件收尾语句
4、v-show: 用来控制元素的显示隐藏(display none block Css切换)
5、v-on (简写@): 用来给元素添加事件。
6、v-bind( 简写:): 用来绑定元素的属性Attr
7、v-model :双向绑定
8、v-for :用来遍历元素
9、v-once:数据只会渲染一次
9、v-memo :性能优化会有缓存
四、虚拟DOM和diff算法
五、Ref
六、Reactive
七、to系列
八、响应式原理代码的实现
九、computed计算属性
十、watch监听
十一、watchEffect高级监听器
十二:生命周期
十三、父子组件传值
1、父组件给子组件传值
2、子组件给父组件传值
十四、组件
局部组件
全局组件
递归组件
动态组件
十五、插槽
十六、异步组件
十七、teleport组件
十八、keep-alive
十九、transition动画组件
二十、transitionGroup
二十一、依赖注入provide、Inject
二十二、兄弟组件传参
二十三、利用已有库Mitt实现Bus
二十四、tsx和vite插件
二十五、v-model
二十六、自定义指令directive
二十七、自定义hooks
二十八、全局函数,全局变量
二十九、自定义vue插件
三十、样式穿透 scoped
三十一、css style完整新特性
三十二、vue3集成Tailwind CSS
三十三、Event Loop事件循环机制
三十四、nextTick
三十五、vue开发移动端
三十六、unocss原子化
三十七、函数式编程,h函数
三十八、vue开发桌面程序electron
三十九、vue响应性语法糖
四十、docker碰撞vue3
四十一、环境变量
配置额外的环境变量
生产环境使用
在vite.config.ts 使用环境变量
四十二、webpack
四十三、性能优化
四十四、web components
四十五、proxy跨域
什么是跨域?
方法一:jsonp
方式二:CORS
方式三:代理。
vue-router
Pinia
方法一:使用vite
npm init vite@latest
安装依赖:npm install
方法二:使用vue脚手架
npm init vue@latest
.vue 件都由三种类型的顶层语法块所组成:、
也可以使用动态事件: 给事件添加修饰符,实现一些功能 .stop:阻止事件冒泡 .prevent:组织表单提交 .once:事件只执行一次 属性包括:style、class、id... 嵌套循环: v-memo="[]",效果和v-once一样 v-memo="[表达式]",符合表达式条件的时候就只渲染一次 vue2和vue3的区别:vue3有最长递增子序列,省去了vue2头尾交换查找一步 被ref包裹的才是响应式数据 支持ts的泛型: shallowRef:浅层次的响应。ref和shallowRef是不能一起写的,否则会影响shallowRef对视图更新 triggerRef:强制shallowRef更新 customRef:一个回调函数,返回一个对象,对象里实现get和set ref与reactive的区别:ref支持所有类型,reactive支持引用类型 reactive是 proxy代理的对象,不能直接赋值,否则会破坏响应式对象。 解决办法一:对于数组,可以push+解构 解决办法二:添加一个对象,将数组作为一个属性 toRef:只能修改响应式对象的值 toRefs:将响应式对象的每一个元素都转换成ref对象。适用场景是解构reactive类型的数据。以下是手动实现 toRaw:数据不需要响应式时,可以用toRaw将响应式数据解出来,还原成原始数据,页面视图就不会更新该数据了 形式一:回调函数 形式二:get、set 三个参数:监听的数据源,回调函数(2各参数:新数据,旧数据),options配置项是一个对象( 常用的属性有=》immediate:true //立即将参数中的回调函数调用一次;deep:true //开启深度监听,flush:"pre"/ "pre" / "post" //组件更新之前 / 同步/ 之后调用 ) 监听多个数据源,采用数组形式: 监听对象,深层次监听需要有deep 与watch的区别:watchEffect是非惰性的,一进页面这个函数就会自动调用,而watch只有在值改变的时候或者配置了immediate的时候才会调用 在监听数据之前可以做一些事情,清除副作用:防抖、清除页面等 停止监听: 一些配置项: vue3的setup语法糖模式没有beforeCreate、created,setup代替beforeCreate、created 创建:创建之前onBeforeMount 、创建完成onMounted 更新:更新之前onBeforeUpdate、 更新完成onUpdated 销毁:销毁之前onBeforeUnmount、销毁完成onUnmounted 当页面有dom时,先进行的是:setup、创建之前onBeforeMount 、创建完成onMounted,创建之前读不到dom,创建之后才能读到 页面数据发生更新后,进行的是:setup、创建之前onBeforeMount 、创建完成onMounted、更新之前onBeforeUpdate、 更新完成onUpdated,更新之前数据还是原始数据,更新之后数据才更新 卸载后,进行的是:setup、创建之前onBeforeMount 、创建完成onMounted、销毁之前onBeforeUnmount、销毁完成onUnmounted 其他的钩子: onRenderTracked:收集依赖去触发的钩子,主要是用来调试的,数据更新前能知道数据长什么样 onRenderTriggered:数据发生修改就会触发,能知道数据被修改 父组件中:子组件的组件标签加上 :数据名="数据具体值" 子组件中:用defineProps接收,在模板中使用{{数据名}} 子组件:需要传递的数据所在标签写上事件,如@click="子组件事件名",然后在setup里写事件的具体操作 父组件:接收数据,在子组件的组件标签上写@自定义名称="父组件事件名",在setup里 子组件暴力方法,父组件如何读取? 子组件暴露方法: 父组件接收: 在子组件的组件标签写:ref="父组件事件",setup里: 可选链操作符 引入再使用 在main.ts引入再注册:app.component("全局组件名称",组件名称) 要记得阻止事件冒泡 多个共同组件内容的切换 v-slot可简写成# 用defineAsyncComponent注册 帮助组件做缓存,默认全部缓存 指定缓存组件 :include=["组件1","组件2",...] 指定不缓存的组件 :exclude=["组件1","组件2",...] 指定缓存组件的个数 :max="数量" 旧的不常用的清除掉,常用的新的放在前面 使用keep-alive增加的生命周期:keep-alive初始化onActivated、keep-alive卸载onDeactivated 使用keep-alive时,会经过onMounted、onActivated keep-alive卸载时,会经过onMounted、onActivated、onDeactivated 根组件使用Provide,子组件都能用到根组件的值,子组件也可以修改根组件的值 根组件:provide("注册的名字",根组件需要传递的数据v-model的名称),如果不想被子组件更改数据,就写成Provide("注册的名字",readonly(根组件需要传递的数据v-model的名称) ) 子组件:const 变量名 = inject("注册的名字") vue3特有功能:css也可以用v-bind(setup里声明的变量),去做该变量的样式改变 方式一:用父组件传参 方式二:Event Bus 利用js的发布与订阅原理,自己写 安装:npm install mitt -S 初始化:main.js 中挂载全局属性 小满Vue3(Mitt) - 哔哩哔哩 (bilibili.com) 语法糖,由props和emit组合而成 vue3与vue2对比,做了哪些修改: 破坏性指令 vue3自定义指令的钩子函数 Vue2 自定义指令的钩子函数 定义自定义指令: 使用自定义指令:在需要的标签上写上v-名称(全小写)="{}" 自定义参数:v-名称(全小写):参数名称="{}" 在钩子函数中能接收到,用...args(因为暂时还不知道有多少参数) 自定义修饰符:v-名称(全小写).修饰符名称="{}" 只用到 鉴权 作用:处理复用代码逻辑的一些封装 Vue3 的 hook函数 相当于 vue2 的 mixin, 不同在与于hooks 是函数 Vue3 的 hook函数 可以帮助我们提高代码的复用性, 让我们能在不同的组件中都利用 hooks 函数 在main.js定义全局变量:app.config.globalPropertied.$变量名 = "显示的内容" 在main.js定义全局方法:app.config.globalPropertied.$方法名 = {方法1(参数){方法具体操作 return 返回值}} 在组建中使用:<标签>{{$变量名}}标签> // 页面上就会出现定义的内容 利用getCurrentInstance获取全局变量、调用全局方法:①引入getCurrentInstance:import {getCurrentInstance} from "vue" ②实例方法获取:const app = getCurrentInstance() ; console.log(app.proxy.$方法名.方法1(参数)) 或者 console.log(app.proxy.$变量名) 对于ts要声明文件 不然TS无法正确类型 推导 在main.js注册全局组件:①引入:import 组件名 from "组件.vue所在目录" ②注册:app.use(组件名) 编写组件:...看不懂 作用:为了修改现成的UI组件库,去做一些定制化的修改 scoped三条渲染规则: 给HTML的DOM节点加一个不重复data属性(形如:data-v-123)来表示他的唯一性 修改插槽样式 :slotted(插槽所在地的类名/id/标签){} 全局样式 :global(类名/id/标签){} 动态css css属性: v-bind(变量名) // 变量名定义的是该样式的名称 css属性: v-bind("变量名.属性1") // 如果变量名定义的是一个对象的写法 css module ① ②<标签 :class="[$变量名style里定义的该样式名称(用id定义的就写#,用类名定义的就写. 以此类推)1,$变量名style里定义的该样式名称(用id定义的就写#,用类名定义的就写. 以此类推)2,...]"> ① ②<标签 :class="[$自定义名称style里定义的该样式名称(用id定义的就写#,用类名定义的就写. 以此类推)1,$自定义名称style里定义的该样式名称(用id定义的就写#,用类名定义的就写. 以此类推)2,...]"> 自定义hook:useCSSModule("style module的自定义名称") 同步任务 异步任务 2.微任务 运行机制 所有的同步任务都是在主进程执行的形成一个执行栈,主线程之外,还存在一个"任务队列",异步任务执行队列中先执行宏任务,然后清空当次宏任务中的所有微任务,然后进行下一个tick如此形成循环。 nextTick 接受一个参数fn(函数)定义了一个变量P 这个P最终返回都是Promise,最后是return 如果传了fn 就使用变量P.then执行一个微任务去执行fn函数,then里面this 如果有值就调用bind改变this指向返回新的函数,否则直接调用fn,如果没传fn,就返回一个promise,最终结果都会返回一个promise 函数式编程用到的是h函数,底层原理是调用createVNode 实验性产物,开发时可以用,生产时不用 看博客 作用:让开发者区分不同的运行环境,来实现 兼容开发和生产。 vite在一个特殊的 这个环境变量不能使用动态赋值import.meta.env[key] 应为这些环境变量在打包的时候是会被硬编码的通过JSON.stringify 注入浏览器的 在根目录新建env 文件 可以创建多个,如:env.[name] 修改启动命令=》在 package json 配置 --mode name 配置智能提示 =》新建env.d.ts App.vue 输出 JSON.stringify(import.meta.env),从控制台看环境是否已经添加进去了 创建 .env.production ,写上VITE_名称大写 = prod 通过环境变量这个值 做一些事情比如 切换接口url 等 一个请求url的 协议、域名、端口 三者之间任意一个与当前页面url不同即为跨域 如何解决? 实现的基本原理是利用了HTML里script元素标签没有跨域限制 动态创建script标签,将src作为服务器地址,服务器返回一个callback接受返回的参数。script标签只能使用GET请求,POST是没法发送的 后端设置,前端设置不了 使用Vite proxy 或者 node代理 或者 webpack proxy,三者用法类似,只是解决dev环境的跨域。 创建一个接口使用express简单构建: 使用vite项目的fetch 请求一下: 存在跨域的,这时候我们就可以配合vite的代理来解决跨域 。在vite.config.js/ts 进行配置: fetch 替换/api 他会截取/api 替换成 target地址: 成功解决! 一、介绍 二、初始化仓库store 三、state 四、解构store 五、actions,getters 六、实例API 七、持久化插件2、v-html:用来展示文本、标签,但不支持组件
3、v-if :用来控制元素的显示隐藏(切换真假DOM)
v-else-if :表示 v-if 的“else if 块”。可以链式调用
v-else :v-if条件收尾语句
4、v-show: 用来控制元素的显示隐藏(display none block Css切换)
5、v-on (简写@): 用来给元素添加事件。
6、v-bind( 简写:): 用来绑定元素的属性Attr
// 绑定了id名称为abc
7、v-model :双向绑定
// 输入框就会有hello
8、v-for :用来遍历元素
9、v-once:数据只会渲染一次
9、v-memo :性能优化会有缓存
四、虚拟DOM和diff算法
五、Ref
function MyRef{value} {
return customRef((track, trigger)=>{
return {
get() {
track() // 收集依赖
return value
},
set (newValue) {
value = newValue
trigger() // 触发依赖
}
}
})
}
六、Reactive
// prevent防止页面刷新
// prevent防止页面刷新
// prevent防止页面刷新
七、to系列
const toRefs =
八、响应式原理代码的实现
九、computed计算属性
十、watch监听
十一、watchEffect高级监听器
十二:生命周期
onRenderTracked((e) => {
console.log(e)
})
onRenderTriggered((e) => {
console.log(e)
})
十三、父子组件传值
1、父组件给子组件传值
js版本:
const props = defineProps({
数据名: {
type: String,
default: "默认值"
}
})
console.log(props.数据名)
ts版本:
const props = defineProps<{
数据名:String
}>()
console.log(props.数据名)
// 定义默认值 withDefaults是ts独有
const props = withDefaults(defineProps<{
数据名:String
}>(), {
数据名:()=> "默认值"
})
console.log(props.数据名))
2、子组件给父组件传值
const emit = defineEmits(["自定义名称1","自定义名称2",...]) // 定义一个数组,数组里事件名称随意写
const 子组件事件名 = () => {
// 派发事件
emit("自定义名称", 参数可多个表示要给父组件的东西)
}
ts版本:
const emit = defineEmits<{
(e:"自定义名称1", 参数:参数类型):返回值(没有返回值就写void)
(e:"自定义名称2", 参数:参数类型):返回值(没有返回值就写void)
(e:"自定义名称3", 参数:参数类型):返回值(没有返回值就写void)
...多个事件的写法
}>()
const getName = (参数:参数的类型) => {
console.log(参数)
}
defineExpose({
事件:事件值
})
const 父组件事件 = ref
十四、组件
局部组件
全局组件
递归组件
动态组件
十五、插槽
十六、异步组件
十七、teleport组件
十八、keep-alive
十九、transition动画组件
二十、transitionGroup
二十一、依赖注入provide、Inject
二十二、兄弟组件传参
二十三、利用已有库Mitt实现Bus
// 引入
import mitt from 'mitt'
// 因为是函数所以声明
const Mit = mitt()
//TypeScript注册
// 由于必须要拓展ComponentCustomProperties类型才能获得类型提示
declare module "vue" {
export interface ComponentCustomProperties {
$Bus: typeof Mit
}
}
// 挂载全局API
app.config.globalProperties.$Bus = Mit
二十四、tsx和vite插件
二十五、v-model
value
-> modelValue
;input
-> update:modelValue
;v-bind
的 .sync
修饰符和组件的 model
选项已移除二十六、自定义指令directive
const v名称(首字母大写): Directive = {
created () {
},
设置各种钩子函数应该做什么
}
mounted
和 updated
时可以简写指令二十七、自定义hooks
二十八、全局函数,全局变量
type 给方法名定义的类型的名字 = { 方法1(参数):返回值类型 }
// 声明要扩充@vue/runtime-core包的声明.
// 这里扩充"ComponentCustomProperties"接口, 因为他是vue3中实例的属性的类型.
declare module 'vue' {
export interface ComponentCustomProperties {
$方法名: 给方法名定义的类型,
$变量名:变量名的类型
}
}
二十九、自定义vue插件
// 该组件的ts文件
import type {App, VNode} from "vue" // 定义插件类型
import 组件名 from "组件.vue所在文件夹"
import {creatVNode, render} from "vue" // 为了转换成VNode
export default { // 暴露
install (app: App) {
const vnode:VNode = createVNode(组件名) // 将组件转成VNode
render(vnode, document.body) // 组件转换成虚拟DOM后component没有值,需要用render挂载 render参数:vnode,挂载点(全局可挂在document.body)
vnode.component.exposed // 获取方法
console.log("我是组件", 组件名) //组件需要做的操作
}
}
// 将组件转成VNode才能挂载到全局使用
三十、样式穿透 scoped
在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-123])来私有化样式。如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性
:deep(){} 改变 属性选择器的位置三十一、css style完整新特性
三十二、vue3集成Tailwind CSS
三十三、Event Loop事件循环机制
代码从上到下按顺序执行
1.宏任务
script(整体代码)、setTimeout、setInterval、UI交互事件、postMessage、Ajax
await后面的内容、Promise.then catch finally、MutaionObserver、process.nextTick(Node.js 环境)
ans:Y 0 5 6 7 8 X 1 2 3 4 三十四、nextTick
三十五、vue开发移动端
三十六、unocss原子化
三十七、函数式编程,h函数
h
函数接收三个参数
三十八、vue开发桌面程序electron
三十九、vue响应性语法糖
四十、docker碰撞vue3
四十一、环境变量
import.meta.env
对象上暴露环境变量:{
"BASE_URL":"/", //部署时的URL前缀
"MODE":"development", //运行模式
"DEV":true," //是否在dev环境
PROD":false, //是否是build 环境
"SSR":false //是否是SSR 服务端渲染模式
}
配置额外的环境变量
interface ImportMetaEnv {
VITE_XIAOMAN:string
}
生产环境使用
在vite.config.ts 使用环境变量
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default ({mode}:any) => {
console.log(loadEnv(mode,process.cwd()))
return defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
}
四十二、webpack
四十三、性能优化
四十四、web components
四十五、proxy跨域
什么是跨域?
方法一:jsonp
function clickButton() {
let obj, s
obj = { "table":"products", "limit":10 }; //添加参数
s = document.createElement("script"); //动态创建script
s.src = "接口地址xxxxxxxxxxxx" + JSON.stringify(obj);
document.body.appendChild(s);
}
//与后端定义callback名称
function myFunc(myObj) {
//接受后端返回的参数
document.getElementById("demo").innerHTML = myObj;
}
复制代码
方式二:CORS
{
"Access-Control-Allow-Origin": "http://web.xxx.com" //可以指定地址
}
{
"Access-Control-Allow-Origin": "*" //也可以使用通配符 任何地址都能访问 安全性不高
}
方式三:代理。
const express = require('express')
const app = express()
//创建get请求
app.get('/xm',(req,res)=>{
res.json({
code:200,
message:"请求成功"
})
})
//端口号9001
app.listen(9001)
复制代码
复制代码
export default defineConfig({
plugins: [vue()],
server:{
proxy:{
'/api':{
target:"http://localhost:9001/", //跨域地址
changeOrigin:true, //支持跨域
rewrite:(path) => path.replace(/^\/api/, "")//重写路径,替换/api
}
}
}
})
复制代码
复制代码
vue-router
Pinia