vue3的基本使用

vue3

vue2和vue3的区别

1、v-if 和v-for

  • 同一元素上使用的v-ifv-for优先级已更改,但不推荐同时使用 v-ifv-for

2、组件事件

  • 组件事件需要在emits选项中声明

3、生命周期

  • destroyed 生命周期选项被重命名为 unmounted
  • beforeDestroy 生命周期选项被重命名为 beforeUnmount

4、自定义指令

  • 自定义指令的API已更改为与组件生命周期一致

5、新增组件

  • 新增了三个组件:Fragment 支持多个根节点、Suspense 可以在组件渲染之前的等待时间显示指定内容、Teleport 可以让子组件能够在视觉上跳出父组件(如父组件overflow:hidden)

6、新增指令

  • 新增指令 v-memo,可以缓存 html 模板,比如 v-for 列表不会变化的就缓存,简单说就是用内存换时间。

7、proxy响应式系统

  • Proxy 代替 Object.defineProperty 重构了响应式系统,可以监听到数组下标变化,及对象新增属性,因为监听的不是对象属性,而是对象本身,还可拦截 apply、has 等13种方法

8、重构DOM和diff算法

  • 重构了虚拟 DOM,在编译时会将事件缓存、将 slot 编译为 lazy 函数、保存静态节点直接复用(静态提升)、以及添加静态标记、Diff 算法使用 最长递增子序列 优化了对比流程,使得虚拟 DOM 生成速度提升 200%

9、在CSS绑定JS变量

  • 支持在 <style></style> 里使用 v-bind,给 CSS 绑定 JS 变量(color: v-bind(str))

10、新增 Composition API

  • 新增 Composition API 可以更好的逻辑复用和代码组织,同一功能的代码不至于像以前一样太分散,虽然 Vue2 中可以用 minxin 来实现复用代码,但也存在问题,比如方法或属性名会冲突,代码来源也不清楚等

11、移除set和delete

  • 全局函数 setdelete 以及实例方法 $set$delete移除。基于代理的变化检测已经不再需要它们了

12、vue3使用Ts写,不兼容IE11

  • 毕竟 Vue3 是用 TS 写的,所以对 TS 的支持度更好
  • Vue3 不兼容 IE11

13、移除实例方法

  • $on$off$once 实例方法已被移除,组件实例不再实现事件触发接口。

组合式API

setup

//方式一:
<script lang="ts">
//optipn API
    //引入
import { defineComponent, onBeforeMount, onMounted } from 'vue'
	//导出
export default defineComponent({
    
  setup(){
    let a = 1
    const test = ()=>{
      console.log('test方法');
      
    }
    onBeforeMount(()=>{
      console.log('挂载前');
      
    })
    onMounted(()=>{
      console.log('挂载后');
      
    })
    return {
      a,
      test
    }
  }
})
</script>

//方式二: 写在script标签上
<script lang="ts" setup>
// 组合式Api
import { onBeforeMount, onMounted, ref ,reactive} from 'vue'

// reactive就可以不用.value了
let a = reactive({
  name:"张三"
});
const test = () => {
  console.log('test方法');
  a.name = a.name+1
}
// 类型可以不屑,会自动推导
let num = ref<number>(1);
const add1 = (): void => {
  num.value++; // 注意通过ref声明的变量,所以js要修改对应的值是要通过.value访问才可以,template模板不需要通过.value访问
};

onBeforeMount(() => {
  console.log('挂载前');

})
onMounted(() => {
  console.log('挂载后');

})

let num1 = ref<number>(0)
let num2 = ref<number>(0)
let count = ref<number | string>("")
const addNum=()=>{
  count.value = num1.value * num2.value
}
</script>

生命周期

下表包含如何在 Option API 和 setup() 内部调用生命周期钩子

Option APIsetup
beforeCreate-
created-
beforeMountOnBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
activatedonActivated
deactivatedonDeactivated

因为 setup 是在 beforeCreatecreated 生命周期钩子前运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。

响应式数据

ref

声明响应式数据,用于声明基本数据类型

//用法:

//引入:
import { ref } from "vue";
//声明变量
let num = ref<number>(1);
//调用或者修改值变化
    const add1 = (): void => {
      num.value++; // 注意通过ref声明的变量,所以js要修改对应的值是要通过.value访问才可以,template模板不需要通过.value访问
    };

//或者可以简写,省略数据类型
const add1=()=>{
   num.value++;
}
  1. ref可以传递基础数据类型和引用数据类型。如果是基础数据类型,那么这个基础数据值保存在返回的响应式数据的.value上;如果是对象,响应式数据在.value上。
  2. ref本质是将一个数据变成一个对象,这个对象具有响应式特点

reactive

reactive声明响应式数据,用于声明引用数据类型

//用法:

//引入:
import { reactive } from "vue";
//声明变量
let state = reactive<ObjItf>(obj);
//或者
let state = reactive({
  name:"张三"
});


//调用或者修改值变化
const test = () => {
  console.log('test方法');
  a.name = a.name+1
}

//或者

const add2 = (): void => {
   state.count++; // 通过reactive声明的遍历,不需要通过.value访问值
};
  1. reactive可以传递基础数据类型和引用数据类型,基础数据类型不会被包装成响应式数据
  2. reactive返回的响应式数据本质是Proxy对象,对象里面每一层都会被包装成Proxy对象
  3. reactive返回的响应式数据和原始的数据会相互影响

toReftoRefs

toReftoRefs整两个方法,它们不创造响应式,而是延续响应式。创造响应式一般由ref和reactive来解决,而toRef和toRefs则把对象的数据进行分解和扩散,其这个对象针对的是响应式对象(reactive)而非普通对象。

 // toRefs解构响应式数据
    let { count } = toRefs<ObjItf>(state);
    const add3 = (): void => {
      count.value++; // 通过toRefs结构的值和ref声明的变量一样,需要通过.value访问其值
    };


toRef

可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。

const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')

fooRef.value++
console.log(state.foo) // 2

state.foo++
console.log(fooRef.value) // 3

//当你要将 prop 的 ref 传递给复合函数时,toRef 很有用:

export default {
  setup(props) {
    useSomeFeature(toRef(props, 'foo'))
  }
}
//即使源 property 不存在,toRef 也会返回一个可用的 ref。这使得它在使用可选 prop 时特别有用,可选 prop 并不会被 toRefs 处理。

Proxy-vue3响应式原理

https://es6.ruanyifeng.com/#docs/proxy

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

    Proxy-vue3响应式原理
    <script>
        let obj = {b:'999'}
        let proxy = new Proxy(obj,{
            get:function(target,propKey){
                console.log(target,propKey);//{x: 123} 'x'
                return target[propKey]
            },
            set:function(target,propKey,value){
                console.log(target,propKey,value);//{} 'x' 123
                target[propKey] = value
            }
        })
        proxy.x = 123
        console.log(proxy.x,obj.x);//123 123
        proxy.b = "你好世界"
        console.log(proxy.b,obj.b);//123 123
    </script>

提交代码风格:https://www.yuque.com/docs/share/e85b95af-9cab-46fb-abb1-a759f5872426?#

事件监听

Watch

语法:watch(监听源|[多个], (val, oldVal) => {}, {immediate?: false, deep: false})

watch写法上支持一个或者多个监听源,这些监听源必须只能是getter/effect函数,ref数据,reactive对象,或者是数组类型

<script lang="ts" setup>
// 组合式Api
import {reactive, ref,toRefs, watch} from 'vue'
let num = ref(1)
let num1 = 1
let obj = reactive({m:1})
let { m } = toRefs(obj)

setTimeout(() => {
  num.value =3;
  num1 = 10;
  obj.m = 999;
}, 1000);

// 监听num
watch(num,(newVal,oldVal)=>{
  console.log(newVal,oldVal);
  // 3 1

})

// 监听num1,如果是普通数据(不是响应数据,这个时候是监听不到的)
watch(()=>num1,(newVal,oldVal)=>{
  console.log(newVal,oldVal);
  
})

// 监听对象obj.属性
watch(()=>obj.m,(newVal,oldVal)=>{
  console.log(newVal,oldVal);
  // 999 1
})
watch(m,(newVal,oldVal)=>{
  console.log(newVal,oldVal);
  // 999 1
})


// 监听多个值变化
watch([num,m],(newVal,oldVal)=>{
  console.log(newVal,oldVal);
  // (2) [3, 999] (2) [1, 1]
})

</script>

watchEffect

它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

<script lang="ts" setup>
// 组合式Api
import {watchEffect,ref} from 'vue'
let num = ref(1)
let num1 = 1


setTimeout(() => {
  num.value++;
  num1 ++;

}, 1000);

watchEffect(()=>{
  // 一开始就会执行一次回调函数,打印出1,1
  // num1不是响应式数据,能打印出2,是因为num.value是响应式数据,响应式数据变化,触发回调函数
  console.log(num1);//2
  console.log(num.value);//2
  
})

</script>

watch 和 watchEffect的区别

  • 两者都可以监听 data 属性变化;
  • watch 需要明确监听哪个属性
  • watchEffect 会根据其中的属性,自动监听其变化。

计算属性computed

<script lang="ts" setup>

import {watchEffect,ref, computed} from 'vue'
let num = ref(1)


setTimeout(() => {
  num.value++;

}, 1000);
// 计算属性
let newNum = computed(()=>{
  return 'ref:num值=' + num.value
})
console.log(newNum);
console.log(num);

</script>

组件

组件注册

局部注册(或者组件内注册)

在使用组件的的XX.vue的文件中,写入

//引入组件
import MyCom from './components/Mycom.vue'

//直接使用
<template>
<!-- 局部组件 -->
  <MyCom></MyCom>
</template>

全局组件

在main.ts文件中,引入

import MyCom1 from './components/Mycom.vue'
//导出
createApp(App).component('my-com',MyCom1).mount('#app')

在使用组件的XXX.vue文件中直接使用

<template>
  <!-- 全局组件 -->
  <my-com></my-com>
</template>

Lodash

Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。

https://www.lodashjs.com/

引入:

第三方库

js-Cookies

https://github.com/js-cookie/js-cookie

查看是否有对应的Ts类型声明的库

https://www.typescriptlang.org/dt/search?search=

路由

路由前置导航守卫

动态生成路由

使用addRoute

在router/index.ts文件中

两种使用方法:

addRoute(parentName: string | symbol, route: RouteRecordRaw): () => void

Parameters

ParameterTypeDescription
parentNamestring | symbolParent Route Record where route should be appended at
routeRouteRecordRawRoute Record to add
addRoute(route: RouteRecordRaw): () => void

插件

时间格式

moment JavaScript 日期处理类库

http://momentjs.cn/

//具体用法:moment(传入要处理的数据).format(数据要处理成的格式)

moment(scope.row.createTime).format('YYYY-MM-DD hh:mm:ss')

手写时间格式处理

// 格式化时间
const formateData = (time: string | undefined) => {
    if (!time) return "";
    const data = new Date(time)
    let year = addZero(data.getFullYear())
    let month = addZero(data.getMonth()+1)
    let day = addZero(data.getDate())
    let hour = addZero(data.getHours())
    let min = addZero(data.getMinutes())
   let sec = addZero(data.getSeconds())
   return `${year}-${month}-${day} ${hour}:${min}:${sec}`
}
const addZero = (num: number) => {
    return num > 9 ? num : '0' + num
}


//然后直接调用方法
formateData(传入实参)

发送请求—request

在src目录下,新建request文件夹下,里面包含两个文件api.ts和request.ts或者是js文件

api.ts 放具体的请求路径……

request.ts 放请求设置,请求拦截器……

发送在URL上带参数的请求

//例如:http://120.24.64.5:8088/mall-admin/admin/list?pageNum=1&pageSize=10&keyword=

//后面带?key=value的

//用params
export const getAdminlistApi = (data:AdminListData):ProminseRes<AdminListRes>=>request.get('/admin/list',{params:data})
//或者写法:ES6写法,key和value相同,可以省略,例如{params:data} ===》{params}
export const getAdminlistApi = (params:AdminListData):ProminseRes<AdminListRes>=>request.get('/admin/list',{params})

api.ts或者api.js文件

//引入reques文件
import request from './request'
// import qs from 'qs'

//类型设置
interface AdminLoginData {
    password: string
    username: string
}

type ProminseRes<T> = Promise<ManageResult<T>>

interface ManageResult<T = {}> {
    code: number;
    data: T
    message: string
}

//登录返回token
interface AdminLoginRes {
    token: string;
    tokenHead: string;
}

// 当前用户信息
interface AdminInfoRes{
    menus:[],
    username:String
}
// 用户列表
interface AdminListRes{
    list:[],
    total:Number,
    totalPage:Number
}
interface AdminListData {
    keyword:string
    pageNum: Number
    pageSize: Number
}

//export导出

// 登录功能
export const LoginApi = (data: AdminLoginData):ProminseRes<AdminLoginRes> => request.post('/admin/login', data)
// 获取用户信息
export const getAdminInfoApi = ():ProminseRes<AdminInfoRes>=>request.get('/admin/info')
// 根据用户名或姓名分页获取用户列表
// export const getAdminlistApi = (data:AdminListData):ProminseRes<AdminListRes>=>request.get(`/admin/list?pageNum=${data.pageNum}&pageSize=${data.pageSize}`)
export const getAdminlistApi = (data:AdminListData):ProminseRes<AdminListRes>=>request.get('/admin/list',{params:data})


request.ts或者request.js文件

import axios from "axios";
import Cookies from 'js-cookie'

let instance = axios.create({
    baseURL: "http://120.24.64.5:8088/mall-admin",
    //响应时间
    timeout: 5000
});
instance.interceptors.request.use(function (config) {
  let token =Cookies.get('token')
  if(token){
    config.headers = config.headers || {}
    config.headers.Authorization = token
  }

    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response.data;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });
  
  export default instance
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值