Vue3

77 阅读9分钟

image-20230915164733042

看源码,github,vue-next,在tag选择相对稳定的版本

在代码上写debugger

打包配置加上sourcemap,debugger定位到源码

vue3基础语法

1.methods中this指向

methods中不能用箭头函数,因为使用箭头函数后,this指向window

2.vs生成代码片段

3.模板语法

vue与react

  • Mustache双大括号语法

  • v-once,只渲染一次,可用于优化性能

  • v-text,v-html

  • v-pre,{{message}}直接显示

  • v-cloak,在编译时设置css,[v-clock]{dispaly:none},闪屏问题

  • v-bind,绑定属性,语法糖 :

    • :class="{'active': boolean}" boolean:data里的响应式变量
    • :class="['active', title, {'isBlue': boolean}]" title、boolean:data里的响应式变量
    • :style="{color: finalColor, fontSize: '30px'}" finalColor:data里的响应式变量
    • :style=[{color: finalColor}, {fontSize: '30px'}] finalColor:data里的响应式变量
    • 动态属性 :[name]="finalName" name、finalName:data里的响应式变量
    • 绑定一个对象 v-bind="info"等价于 :name=”shan“ :age=”16“,会自己将对象里的属性绑定到元素上
  • v-on,绑定事件,语法糖@

    • v-on:click="btnClick" @click="btnClick"
    • 多个事件 v-on="{click: btnClick, mousemove: mouseMove}"
    • 传参 @click="btnClick(event,name,age)"默认会传event,带其他参数时用event, name, age)" 默认会传event,带其他参数时用event
  • 条件渲染 v-if、v-else-if、v-else;v-show

  • template 不可见的包裹元素,可与v-if、v-for搭配使用

  • 循环渲染 v-for

    • 数组 v-for="(item, index) in arr"

    • 对象 v-for="(value, key, index) in obj"

    • 数字 v-for="(num, index) in 10"

    • vue将监听数组的变更方法进行了包裹(改变数组)

      • push/pop/shift/unshift/splice/sort/reverse
    • 产生新数组

      • filter/concat/slice
  1. computed 计算属性:会基于它们的依赖关系进行缓存。当依赖的数据发生变化,计算属性才会重新进行计算

    computed: {
        fullName: {
            get: function(){
                return this.firstName + "-" + this.lastName
            },
            set: function(newValue){
                console.log(newValue)
            }
        }
    }
    

5.watch 侦听器:只侦听info的引用变化,对内部属性不做出响应

  • deep: true 深层监听
  • immediate: true 立即执行一次

表单绑定

v-model

  • <input type="text" v-model="message">

  • 语法糖,实际两操作

    • :value = "message"v-bind 绑定一个 value 属性
    • @input = "message = $event.target.value"v-on 给当前绑定 input 事件
  • 修饰符

    • v-model.lazy:将@input变为@change
    • v-model.number:v-model默认赋值为string,number可改为number
    • v-model.trim

组件化开发

  • 注册全局组件 app.component("component-a", {template: "我是组件a"})

webpack

  • 视频上的node版本v14.15.5,npm是6.14.11

    • 我的image-20230918155021994
  • webpack is a static module bundler for modern JavaScript applications

    • webpack是一个静态的模块化打包工具,为现代JavaScript应用程序

      • 打包bundler

      • 静态static:打包成静态资源部署到静态服务器

      • 模块化module:支持各种模块化开发,ES Module、CommonJS等

        • CommonJS

          • 导出:module.exports = {one: 1, two: 2}
          • 导入:let {one, two} = require("./a.js")
        • ES6 的 Modules

          • 导出:export
          • 导入:import
      • 现代modren:现代前端问题,优化等

对应目录01webpack
  • npm init
    npm install webpack webpack-cli -D
    
  • 安装vscode插件Live Server

loader-帮助加载模块

  • 对特定的模块类型进行转换
npm install css-loader style-loader less-loader -D
​
npm install --save-dev postcss-loader postcss
npm install postcss-preset-env -D
​
npm install file-loader -D
npm install url-loader -D
  1. css
  • less-loader解析.less文件,css-loader将.css文件解析,style-loader将其插入

  • postcss

    • 一个通过JavaScript来转换样式的工具

    • 可以通过添加插件进行一个css的转化和设配,比如添加浏览器前缀、css新属性适应等

    • 可以在postcss.config.js中配置插件,然后在loader中引入,也可以直接在loader里配置

      • 插件autoprefixer添加前缀
      • 插件postcss-preset-env更强大,且包含了autoprefixer的功能

2.图片

  • file-loader,图片,帮助处理import/require()方式引入的文件资源

    • import oneImage from '../img/1.png'
    • 要把图片当成一个模块去引入,不然打包时找不到对应图片
  • url-loader,可以将较小文件转成base64的URL

    • 对服务器高并发有优化作用。不处理的话,加载一张图片需要向服务器发送一次请求,将其转化为base64后,会集成到js文件中,随着js文件的请求一起传给浏览器,由浏览器解析显示,不需要单独请求
  • asset module type

    • webpack5新特性
  1. 加载字体,和图片类似

plugin-执行更加广泛任务

  • 比如打包优化、资源管理、环境变量注入等
npm install clean-webpack-plugin -D
npm install html-webpack-plugin -D
npm install copy-webpack-plugin -D
  • CleanWebpackPlugin 删除dist文件夹
  • HtmlWebpackPlugin 插入html模板
  • CopyWebpackPlugin 复制public目录下的部分文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { DefinePlugin } = require("webpack")
const CopyWebpackPlugin = require("copy-webpack-plugin")
​
plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
        template: "./public/index.html",
        title: "Webpack5"
    }),
    new DefinePlugin({
        BASE_URL: "'./'",
    }),
    new CopyWebpackPlugin({
        patterns: [
            {
                from: "public",
                to: "./",
                globOptions: {
                    ignore: [
                        "**/index.html"   // 忽略的文件
                    ]
                }
            }
        ]
    })
]

mode和devtool

mode: "development",  // 开发阶段,打包上线->production
devtool: "source-map",  // 建立js映射文件,方便调试代码和错误

Babel - JS编译器

  • 将写的源代码转为浏览器可识别的另外一段源代码。语法转化、源代码转换
npm install @babel/core @babel/cli -D 核心代码,必须安装
​
npm install @babel/plugin-transfrom-arrow-functions -D  转化箭头函数
npm install @babel/plugin-transfrom-block-scoping -D 转化块级作用域
以上两个也在下面这个中集成
npm install @babel/preset-env -D
​
webpack用babel
npm install babel-loader @babel/core -D
npm install @babel/preset-env -D
  • 推荐阅读,简易编译器代码

  • Babel编译器执行原理(理解)

  • babel可直接在module中配置,也可写配置文件babel.config.json

devServer

  • 两种常用监听文件改动自动打包方法

    • 直接配置watch:true + vscode插件live-server(自动刷新浏览器)
    • webpack-dev-server
  • webpck-dev-server

    • npm install webpack-dev-server -D

    • #package.json
      "scripts": {
          "build": "webpack",
          "serve": "webpack serve",
       },
      
    • 配置项contentBase,主要用于开发阶段,不复制,直接去访问

      • webpack4的contentBase,webpack5要用static
      • 打包阶段,用copy-webpack-plugin复制一份到打包文件里
      • 理解contentBase
    • 模块热替换(HMR,Hot Module Replacement)

      • 在运行过程中,替换、添加、删除模块,以模块更新为单位,无需重新刷新整个页面

      • Http和socket

        • Socket长连接,即时通信,通过心跳包判断
        • Http短连接,客服端发送请求->和服务器建立连接->服务器做出相应->断开链接
    • proxy

      • 代理服务器(和浏览器的域名/端口一致(记得是))
      • 代理服务器和API服务器没有跨域问题,就可以解决浏览器的跨域问题了
    • resolve模块,解析文件路径

      • extensions 扩展名
      • alias 别名

vue

npm install vue@next
​
写.vue文件
npm install vue-loader@next @vue/compiler-sfc -D
  • vue打包后有不同版本

    • cdn引入一般是vue.global.js,全局暴露一个vue对象
    • runtime的版本不能解析template,没有编译器
    • import { createApp } from 'vue/dist/vue.esm-bundler' // 要选择版本
      const app = createApp({
          template: `<h1>Vue render</h1>`,
          data() {
              return {}
          }
      });
      app.mount("#app")
      
  • vsCode对.vue文件,安装 volar插件

  • webpack配置vue

    • const { VueLoaderPlugin } = require("vue-loader/dist/index")
      module.exports = {
          mudule: {
              relus: [
                  {
                      test: /.vue$/,
                      loader: "vue-loader",
                  }
              ]
          },
          plugins: [
              new DefinePlugin({ // 警告,建议配置,利于tree-shaking(打包时,没用到的不打包)
                  __VUE_OPTIONS_API__: true,
                  __VUE_PROD_DEVTOOLS__: false,
              }),
              new VueLoaderPlugin()
          ]
      }
      

webpack配置分离

  • npm install webpack-merge -D
  • #package.json
    "build": "webpack --config ./config/webpack.prod.config.js",
    "serve": "webpack serve --config ./config/webpack.dev.config.js",
    

Vue Cli

npm install @vue/cli -g
npm update @vue/cli -g
vue create 项目的名称
  • vue-cli service 源码解析,视频10,时间00:50:00,没看懂

Vite

  • 浏览器可解析ES6 module,但是不能加载.ts,.vue等文件,且依赖包的管理不足(会请求很多依赖文件)

  • vite

    • 安装对应工具包(postcss、less)会自动转化代码,复杂的还是需要额外的配置文件
    • serve ,可以将ts、less转化为js代码(es6),还是一个个文件的形式
    • build,会将node_moudle里的引入包做预打包,再次打包时会直接用之前的,减少打包时间
  • package.json

    • "scripts": {
          "serve": "vite",
          "build": "vite build",
          "perview": "vite preview"
      }
      

组件化开发

  • vscode插件 vue3-snippets-for-vscode、vetur

组件的拆分和嵌套

  • components

组件的css作用域

组件通信

父子组件
  • 父->子 props属性

    • type类型:String、Number、Boolean、Array、Object、Date、Function、Symbol

    • 数组和对象默认值必须从工厂函数获取,default() { return {}|[]}

      • return 会返回一个新对象或数组,各组件间就不会相互影响
    • 非props的Attribute

      • 当子组件为单个根节点时,非prop的Attribute将自动添加到根节点的Attribute中,如class、style

      • 不想继承时,子组件设置inheritAttrs: false

      • 当子组件有多个根节点时,会报警告,需手动指定将属性绑到哪个节点上

        子->父 $emit 触发事件

非父子组件通信
  • provide、inject

    • 不管层级多深,父组件可以作为所有子组件的依赖提供者
  • mitt全局事件总线

    • npm install mitt
    • #util/eventBus.js
      import mitt from 'mitt'
      const emitter = mitt()
      export default emitter
      
    • // 发送
      btnClick(){
          emitter.emit("shan", {name: "shan"})
      }
      // 监听
      emitter.on("shan", (info)=>{})
      ​
      // 取消
      emitter.all.clear()
      ​
      function onFun(){}
      emitter.on('foo',onFun)  // 监听
      emitter.off('foo',onFun)  // 取消监听
      

插槽

  • 匿名插槽

  • 具名插槽

    • 父 <template v-slot:center> 内容 </template>
      父简写 <template #center> 内容 </template>
      子 <slot :name="center"></slot>
      
  • 动态插槽

    • 父 <template v-slot:[name]></template>
      
  • 渲染作用域

    • 父级模板的所用内容在父级作用域中编译
    • 子模板的所用内容在子作用域中编译
  • 作用域插槽

    • 插槽可以访问到子组件中的内容,比如渲染数组元素时使用插槽
    • <show-names :name="names">
          <template v-solt="slotProps">
              <button>{{slotProps.item}}-{{slotProps.index}}</button>
          </template>
      </show-names><div>
          <template v-for="(item,index) in names" :key="item">
              <slot :item="item" :index="index"></slot>
          </tempalate>
      </div>
      

动态组件

  • <component :is="currentTab"></component>
    

keep-alive

  • 保存组件状态,不销毁

  • <keep-alive>
        <component :is="currentTab"></component>
    </keep-alive>
    
  • 属性

    • include,名称匹配的组件被缓存,匹配组件自身的name选项
    • exclude,名称匹配的组件不被缓存
    • max,缓存组件达到这个数字,最近没有被访问的组件会被销毁

Webpack代码分包

  • 默认情况下,在构建组件树的过程中,组件和组件间通过模块化直接形成依赖,webpack在打包时会将组件模块打包到一起,比如一个app.js
  • 随着项目扩大,app.js文件过大,会造成首屏的渲染速度变慢。
  • 对于一些不需要立即使用的组件,单独对它们进行拆分,拆分成小的代码块chunk.js

异步组件

  • import

  • vue3

    • import { defineAsyncComponent } from 'vue';
      ​
      const AsynCategory = defineAsynComponent(()=>import("./AsyncCategory.vue"))
      // 或者对象写法
      const AsynCategory = {
          loader: ()=>import("./AsyncCategory.vue"),  // 工厂函数
          loadingComponent: 加载时的运行组件,
          errorComponent: ,
          delay: 2000, // 在显示loadingComponent前的等待事件
      }
      

$refs

  • 绑定一个元素上
    <h2 ref="title"></h2>
    绑定组件实例上
    <nav-bar ref="navBar"></nav-bar>
    ​
    取 this.$refs.title,dom元素
    取 this.$refs.navBar,组件实例
    

parentparent、root

  • this.$parent,父组件实例
  • this.$root,根组件实例

组件生命周期

组件v-model

  • 父
    <s-input v-model:model-value="message"></s-input>
    相当于 <s-input modelValue="message" @update:model-value="message = $event"></s-input>
    ​
    子
    <div>
        <input v-model="value">
    </div>
    {
        ...,
        props: {
            modelValue: String,
        },
        emits: ["update:modelValue"],
        // 自定义表单,比较优雅的写法
        computed: {
            value: {
                set(value) {
                    this.$emit("update:modelValue", value)
                },
                get() {
                    return this.modelValue;
                }
            }
        }
    }
    

vue3过渡和动画实现

transition

  • vue提供了transition的封装组件,可以给单个组件或元素加过渡效果

    • 条件渲染(v-if、v-show)
    • 动态组件
    • 组件根节点
  • <transition name="shan">
        // type - animation 或 transition
        <h2 v-if="show" type="animation">Hello</h2>
    </transition>
    ​
    // 淡入淡出 transition
    <style scoped>
        .shan-enter-from,
        .shan-leave-to {
            opacticy: 0
        }
        
        .shan-enter-to,
        .shan-leave-from {
            opacity: 1
        }
        
        .shan-enter-active,
        .shan-leave-active {
            transition: opacity 1s ease;
        }
    </style>
    ​
    // 弹 animation
    <style scoped>
        .shan-enter-active {
            animation: bounce 1s ease;
        }
        .shan-leave-active {
            animation: bounce 1s ease reverse;
        }
        
        @keyframes bounce {
            0% {
                transform:scale(0)
            }
            50% {
                transform:scale(1.2)
            }
            100% {
                transform:scale(1)
            }
        }
    </style>
    
  • 当插入/删除包含transition组件中的元素时

    • 判断目标元素是否应用css过渡或动画,如果有,在恰当事件添加/删除 css 类名,没有的话,插入/删除操作会立即执行
  • 还有其他属性,看vue官方文档

animate.css

  • 第三方动画库,跨平台动画库
  • npm install animate.css
  • #main.jsimport "animate.css"
    
  • bounceInUp动画库提供的名称
    .shan-enter-active {
        animation: bounceInUp 1s ease;
    }
    ​
    也可以使用自定义class
    <transition enter-active-class="animate__animated animate__fadeInDown">
        <h2 v-if="show">Hello</h2>
    </transition>
    

gsap库

  • 通过 js 为css属性、SVG、Canvas等设置动画

  • transition组件有对应js钩子

    • <transition
          @before-enter="beforeEnter"
          @enter="enter"
          @after-enter="afterEnter"
          ......
      >
      </transition>
      

transition-group

  • 列表动画,移除、插入、移动、交错(data-Index(el.dataset.index),delay)

Mixin

  • vue组件中的可复用功能

    • mixins: [demoMixin]
  • Mixin合并规则

    • data,合并,发生冲突,保留组件自身数据
    • 生命周期钩子函数,合并到数组中,mixin先
    • 指为对象的选项(methods/components/directives),合并,发生冲突(key相同),取组件的

extend(了解)

  • 了解,可被mixin替代extends: BasePage

Composition API

15、16

  • options API对应属性编写对应功能模块

    • 实现某个功能时,对应代码逻辑会被拆分到各个属性,阅读性差
  • Composition API能将同一逻辑相关的代码放在一块,阅读性更好

setup函数

  • setup函数中没有this

  • 可以替代vue2的大部分选项,如methods、computed、watch、data、生命周期等

  • 参数

    • props

      • 父组件传递过来的属性会放入props对象
    • context

      • attrs:所有非prop的attribute
      • slots
      • emit
  • 返回值,给模板使用

script setup
<script setup></script>

reactive API

import { reactive } form "vue"
const state = reactive({
    name: "shan",
    counter: 100
})
  • 使用reactive处理数据后,再次使用会进行依赖收集
  • 当数据发生改变时,收集到的依赖会进行对应的响应式操作(比如更新界面)
  • 其他API
reactive 其他API
  • isProxy,是否由 reactive/readonly 创建的proxy
  • isReactive
  • isReadonly
  • toRaw
  • shallowReactive

ref API(推荐使用,利于代码分离)

import { ref } form "vue"
const name = ref("shan")
  • ref 返回一个响应式对象,该对象作为一个响应式的引用
  • 模板引用ref值时,会自动进行解包,可以直接用{{name}}
  • 在setup函数内部,依然是一个ref引用,要使用name.value的方式
toRefs
  • 将reactive对象里所有属性转为ref,建立引用
  • const info = reactive({name: "shan", age: 16})
    ​
    let {name,age} = toRefs(info) //直接解构就不是响应式数据,得用toRefs
    
toRef
  • 将reactive对象里其中一个属性转为ref,建立引用
  • const info = reactive({name: "shan", age: 16})
    ​
    let age = toRef(info, "age")
    
customRef(自定义ref)
  • export default function(value) {
        let timer = null;
        
        return customRef((track, trigger) => {
            return {
                get() {
                    track();
                    return value
                },
                set(newValue) {
                    clearTime(timer);
                    timer = setTimeout(()=>{
                        value = newValue;
                        trigger()
                    },1000)
                }
            }
        })
    }
    
模板中使用ref
  • <h2 ref="title"></h2>
    
    <script>
        import {ref, watchEffect} from 'vue';
        export default {
            setup() {
                const title = ref(null) // 初始值给null
    
                watchEffect(() => {
                    // title.value
                },{
                    flush: "post" // 挂载后操作
                })
    
                return {
                    title // 返回了,就可以直接在模板用
                }
            }
        }
    </script>
    
其他 ref API
  • unref 等价于 val = isRef(val) ? val.value : val
  • isRef
  • shallowRef
  • triggerRef:手动触发和 shallowRef 相关的副作用

readonly

import { readonly } form "vue"
const nameRead = readonly("shan")
  • reactive或ref会返回一个响应式对象,传给其他组件时,不希望被修改,可以用readonly
  • readonly返回原生对象的只读代理,proxy的set方法被劫持

侦听

computed
const fullName = computed(() => firstName.value + lastName.value)
  • 接受一个getter函数,或者get和set的对象,返回ref对象
watchEffect
  • 基本使用

    • 传入会立即执行一次,并在执行时收集依赖(响应式数据)。依赖发生变化时,函数会再次执行
    • watchEffect(() => {
      	console.log("age",age.value)
      }
      
  • 停止侦听,返回值 stop

  • 清除副作用,参数onInvalidate

    • watchEffect 的 函数即将重新执行或侦听被停止(stop被调用)时会执行onInvalidate传入的回调函数
    • const stop = watchEffect((onInvalidate) => {
      	const timer = setTimeout(()=>{
      		// 模拟网络请求
      	},2000)
      	
      	onInvalidate(()=>{
      		clearTimeout(timer)
      	})
      	console.log("age",age.value)
      }
      
      const changeAge = () => {
      	age.value++
      	if(age.value > 25) {
      		stop()
      	}
      }
      
  • 执行时机(flush)

    • 默认值pre,元素挂载前执行
    • post,元素挂载后
    • watchEffect(()=>{
      	let content = titleRef.value
      }, {
      	flush: "post"
      })
      
watch
  • 与option中的类似

  • 与watchEffect比较

    • 惰性,第一次不会直接执行
    • 具体说明哪些变量发生变化触发执行
    • 访问状态变化前后的值
  • 单个数据源

    • 1.getter函数,newValue,oldValue是本身
      2.传入reactive对象,newValue,oldValue也是reactive对象
      3.传入reactive对象,newValue,oldValue是value值本身
      
      watch(()=>info.name, (newValue,oldValue) => {
      	// newValue,oldValue
      }, {
      	deep:true,
      	immediate: true
      })
      
  • 多个数据源

    • watch(()=>[...names], (newValue,oldValue) => {
      	// newValue,oldValue => 普通的值
      })
      

生命周期钩子

  • beforeCreate、created没有对应的,在setup里直接写就行,setup围绕着着两个周期执行
  • onBeforeMount
  • onMounted
  • onBeforeUpdate
  • onUpdated
  • onBeforeUnmount
  • unmounted
  • onActivated
  • onDeactivated

provide、inject

// 一般包层readonly,组件间数据传递保持单向
provide("name", readonly(name))

const name = inject("name")

hook示例

  • useCounter

  • useTitle

  • useScrollPosition

    • #App.vue
      <div class="scroll">
      	<div>scrollX: {{scrollX}}</div>
      	<div>scrollY: {{scrollY}}</div>
      </div>
      
      <script>
      	import useScrollPosition from './hook/useScrollPosition'
      	export default {
      		setup() {
      			const {scrollX, scrollY} = useScrollPosition()
      		}
      		
      		return {
      			scrollX, 
      			scrollY
      		}
      	}
      </script>
      
      <style>
      .scroll {
      	position: fixed;
      	right: 30px;
      	bottom: 30px;
      }
      </style>
      
    • #useScrollPosition.js
      export default function() {
      	const scrollX = ref(0)
      	const scrollY = ref(0)
      	
      	document.addEventListener("scroll", () => {
      		scrollX.value = window.scrollX
      		scrollY.value = window.scrollY
      	})
      	
      	return {
      		scrollX,
      		scrollY
      	}
      }
      
  • useLocalStorage

    • #App.vue
      // 取值
      const data = useLocalStorage("name")
      // 保存值
      const data = useLocalStorage("name", "shan")
      // 改值
      data.value = "xiao"
      
    • #useLocalStorage.js
      export default function(key, value) {
      	const data = ref(value)
      	
      	if(value) {
      		window.localStorage.setItem(key, JSON.stringify(value))
      	}else {
      		data.value = JSON.parse(window.localStorage.getItem(key))
      	}
      	
      	watch(data, (newValue) => {
      		window.localStorage.setItem(key, JSON.stringify(value))
      	})
      	
      	return {
      		data
      	}
      }
      

h函数(渲染函数)

  • vue会将template中的HTML转换为VNode,VNode组合在一起形成树结构(VDOM)

  • h()是一个创建vnode的函数,creatVNode()

  • h()参数

    • HTML标签名,组件,必需
    • props,可选
    • 内容,可选
  • 基本使用

    • <script>
      import { h } from 'vue';
      
      export default {
        render() {
          return h("h2", {class: "title"}, "HelloWorld")
        }
      }
      </script>
      
  • 实现计数器

  • 插槽的使用 - 官网也有说明

  • vue中使用jsx

    • jsx通过Babel进行转换(React编写jsx也是通过babel转换)

    • 在Babel中配置插件(高版本vue已有集成)

      • npm install @vue/babel-plugin-jsx -D
      • #babel.config.js
        module.exports = {
            presets: [
                "@babel/preset-env"
            ],
            plugins: [
            	"@vue/babel-plugin-jsx"
            ]
        }
        
    • 使用实例

      • <script>
        export default {
          render() {
            return <div>HelloWorld</div>
          }
        }
        </script>
        

vue3高级用法

自定义指令 18

  • 对DOM元素进行底层操作,这个时候用自定义指令

  • 局部指令

    • <template>
      	<div>
      		<input type="text" v-focus>
      	</div>
      </template>
      <script>
      	export default {
      		// 局部指令
      		directives: {
      			focus: {
      				mounted(el, bindings, vnode, preVnode) {
      					el.focus() // 输入框内自带此函数
      				}
      			}
      		},
              setup() {}
      	}
      </script>
      
  • 全局指令

    • app.directive("focus", {
      	mounted(el, bindings, vnode, preVnode) {
          	el.focus() // 输入框内自带此函数
          }
      })
      
  • 指令的生命周期

    • created(vue2 - 无)
    • beforeMount(vue2 - bind)
    • mounted(vue2 - inserted)
    • beforeUpdate(vue2 - 无)
    • updated(vue2 - componentUpdated)
    • beforeUnmount(vue2 - 无)
    • unmounted(vue2 - unbind)

Teleport-vue3新内置组件

  • 移动元素位置
  • <teleport to="放在哪#shan"></teleport>
    

vue插件

  • # main.js
    app.use(pluginObject)
    
    # plugin_object.js
    export default {
    	install(app) {
    		//
    	}
    }
    

路由

Vuex

vue2和vue3

  • template

    • vue2 template模板中只能有一个根元素
    • vue3 template中允许有多个根元素
  • 过滤器

    • vue3不支持过滤器,用计算属性computed或方法method替代
  • $children

    • vue3移除了$children

其他

filter、map、reduce

深拷贝和浅拷贝

  • Object.assign({}, item) 浅拷贝

  • 用lodash

    • const obj = _.clone(info) 浅拷贝
    • const obj = _.cloneDeep(info) 深拷贝