vue3学习

作者: 菜蚴菜 | 来源:发表于2022-02-04 19:41 被阅读0次

一、基础语法

1、双向数据绑定

vue2

      //defineProperty 无法直接监听到元素的增加,删除
        let person = {
            name: 'hello'
        }
        let p = {}
       把值通过遍历做数据劫持
        Object.defineProperty(p, 'name', {
            get() {
                return person.name
            },
            set(value) {
                console.log('变更后的值为:', value)
                person.name = value
            }
        })
        p.name = 'world'

vue3

        let person = {
            name: 'hello'
        }
        let p = new Proxy(person, {
            get(target, propName) {
                return Reflect.get(target, propName)
            },
            set(target, propName, value) {
                Reflect.set(target, propName, value)
            },
            deleteProperty(target, propName) {
                Reflect.deleteProperty(target, propName)
            }
        })
        p.name = "world"
2、ref, reactive

ref:一般用在定义基本类型和引用类型,如果是引用类型底层会借助reactive形成proxy代理对象,可以直接复制整个对象,如table的数据请求回来,需要将数据整体赋值个响应对象这时如果使用的是reactive就无法进行响应。

reactive:一般用在引用类型,如{}等,不能一次性修改整个对象,如我们后端请求table的数据数据,如果想一次性赋值的整个数组的话,就行不通,此时建议使用ref来定义数组。

!!!注意
let obj=reactive([])
setTimeout(()=>{
     let arr=[1,2,3]
     //当页面初始化完成以后,这种直接赋值会改变obj的对象指向,是不会生效的
     obj=arr
},1000)

ref还可以获取元素

注意:

在vue3中私用ref 等api需要手动引入,如果不想手动引入的话可以使用setup语法糖插件
1、npm i unplugin-auto-import -D
2、在vite.config.js中配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(),
    AutoImport({
      imports:['vue','vue-router'],
      dts:"src/auto-import.d.ts"//生成auto-import.d.ts全局声明
    })
  ]
})
3、toRef toRefs 把变量变成ref
<template>
  <div>{{name}}</div>
</template> 

return {
    name:toRef(person,'name')
或者
    ...toRefs(person)
}
// 如果想在setup语法糖中使用toRefs
<script setup lang="ts">
let person = reactive({
  name: "hello"
});
const { name } = toRefs(person);
</script>
4、shallowReactive,shallowRef 浅层次的响应式

shallowReactive只处理对象最外层的响应。如果一个对象数据,结构比较深,但变化时只是外层属性变化
shallowRef只处理基本数据类型的响应式,不处理对象类型的响应式。如果一个对象数据,后续不会修改该对象中的属性,而是生新的对象来替换。

5、readonly shallowReadonly

readonly:让一个响应式变为只读(深只读)(person=readonly(person))
shallowReadonly:让一个响应式变为只读(浅只读,不能更改最外层的数据)

6、toRaw markRaw

toRaw
将一个由reactive生成的响应式Proxy对象转为普通对象
适用场景:用于读取响应式对象对应的普通对象,对这个普通对象做操作不起作用
markRaw
标记一个对象使其永远不会再成为响应式对象
应用场景:
①、有些值不应被设置为响应式,例如复杂的第三方类库
②、当渲染具有不可变数据源的大列表时,跳过响应式转换可提高性能
③、当添加的元素不想做响应式,但值会正常发生改变:person.car=markRaw('ffff')

7、customRef

创建自定义的ref,并对其依赖项跟踪和更新触发进行显示控制

 let custom = myRef('hello')
    //自定义ref名称为myRef
    function myRef(value) {
      return customRef((track, trigger) => {
        return {
          get() {
            console.log('获取最新的值')
            track()//追踪当前数据
            return value
          },
          set(newValue) {
            console.log('收到最新的值', value)
            value = newValue
            //通知vue重新解析模板
            trigger()
          }
        }
      })
    }
8、provide inject

祖孙组件传值

//祖组件
setup(){
    let obj={}
    provide('obj,obj)
}
//孙组件
setup(){
    let obj=inject('obj)
}
9、props

//需要在props中定义

props: {
    msg: String,
  },
  setup(props, context) {
    //context为执行上下文
    let name = ref(props.msg)
}
//如果是使用了setup语法糖(仅限类型的 props 声明)
1、 `defineProps` 可以使用运行时声明和类型声明两种方式(详见[官方文档](https://link.juejin.cn/?target=https%3A%2F%2Fv3.cn.vuejs.org%2Fapi%2Fsfc-script-setup.html%23%25E4%25BB%2585%25E9%2599%2590-typescript-%25E7%259A%2584%25E5%258A%259F%25E8%2583%25BD "https://v3.cn.vuejs.org/api/sfc-script-setup.html#%E4%BB%85%E9%99%90-typescript-%E7%9A%84%E5%8A%9F%E8%83%BD")),但是不能同时使用。为了使 TS 更好的流转,实践中建议使用上例中的**类型声明**方式。
2、withDefaults 用来声明 props 的默认值,使用方式与运行时声明定义 default 的格式一样
interface Props {
  msg?: string
  labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})
10、emit

需要在emits中定义

 emits: ['hello'],
//setup中
 function sayHello() {
      context.emit('hello')
    }
//在setup语法糖中
// e 为 emit 的名字,第二个参数的 key 可以随意定义
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
11、computed
   let fullName = computed(() => {
      return `${props.msg}${props.age}`
    })
12、watch watchEffect

首次加载不会监听,只会被监听数据发生变化时才监听到。(惰性)
可以拿到新的值以前的值
可以同时监听多个数据的变化
①、监听ref定义的变量 1个或多个

watch(job, (value) => {
    console.log('值变化了', value)
  })

//多个时,返回值为数组

watch([job, hobby], (value) => {
    console.log('值变化了', value)
  }, { immediate: true})

②、监听relative所定义的响应式数据的全部属性
注意1、此处无法正确获取到oldValue
2、强制开启了深度监听(deep配置无效)

watch(obj, (newValue,oldValue) => {
      console.log('值变化了', value)
    })

③、监听relative所定义的响应式数据的某些属性,props中的数据的监听同理

watch(() => props.msg, (value) => {
   console.log('值变化了', value)
 }, { immediate: true })
//监听某些具体的属性为对象,deep是起作用的
 watch([() => obj.name,() => obj.age], (value) => {
   console.log('值变化了', value)
 },{deep:true})

watchEffect的特性
首次加载就会监听
只能拿到最新的值
不需要指定监听的数据,组件初始化的时候就会执行一次用以收集依赖,而后收集到的依赖发生变化,这个回调才会再次执行
有点像computed,但computed更注重计算出来的值,必须写返回值。watchEffect更注重过程,不用写返回值。

  watchEffect(() => {
      console.log('发生变化',job.value) // ref  类型的需要加.value
    })
13、生命周期及对应写入setup中的表示

生命周期           setup中
beforeCreate     setup()
created              setup()
beforeMount      onBeforeMount
mounted            onMounted
beforeUpdate    onBeforeUpdate
updated             onUpdated
beforeUnmount  onBeforeUnmounted
unmounted         onUnmounted

13、自定义hook函数

把setup中使用的composition API进行封装,类似于mixin

//hook->usePoint.ts
import {  reactive,onMounted } from 'vue';
export default function(){
    //实现鼠标打点的数据
    let point = reactive({
        x: 0,
        y: 0
      })
      onMounted(() => {
        window.addEventListener('click',(event) => {
          point.x = event.pageX
          point.y = event.pageY
        })
  
      })
      return point
}
//使用时
import usePoint from './hooks/usePoint'
let point=usePoint()
14、响应式数据的判断

isRef
isReactive
isReadonly
isProxy:检查一个对象是否由reactive或者readonly方法创建的代理
fragment(片段)
组件没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中

15、teleport(传送)

能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术

 <button>显示弹窗</button>
 <teleport to="body">
    <div>弹窗内容</div>
 </teleport>
16、defineAsyncComponent

等待异步组件时渲染一些额外的内容,让应用有更好的用户体验。
缺点:在网速慢的时候会有抖动的效果。使用Suspense进行占位(这个是实验属性)。

  <Suspense>
    <template v-slot:default>
      <Child></Child>
    </template>
    <template v-slot:fallback>占位内容</template>
  </Suspense>

import { defineAsyncComponent } from 'vue';
const Child=defineAsyncComponent(()=>import('./components/Child'))//异步引入
export default defineComponent({
  name: 'App',
  components: {
   Child
  },
}

二、差异调整

api调整

2.X全局api                       3.X实例api
Vue.config.xxx                  app.config.xxx
Vue.config.productionTip   移除
Vue.component                 app.component
Vue.directive                     app.directive
Vue.mixin                           app.mixin
Vue.use                             app.use
Vue.prototype                    app.config.globalProperties

其他调整

①、data选项应始终被生命为一个函数
②、过渡类名的更改
vue2.x

.v-enter,                             
.v-leave-to{
opacity:0;
}
.v-leave,
.v-enter-to{
opacity:1;
}

vue3.x

.v-enter-from,                             
.v-leave-to{
opacity:0;
}
.v-leave-from,
.v-enter-to{
opacity:1;
}

事件修饰符(不变此处记录一下)

.prevent:阻止默认事件
.stop:阻止事件冒泡
.once:事件只触发一次
.capture:使用事件的捕获模式
.self:只有event.target是当前操作的元素时才触发事件
.passive:事件的默认行为立即执行,无需等待事件回调执行完毕

③、移除keyCode作为v-on的修饰符,同时也不再支持config.keyCode
不能使用@keyup.13这种使用方法
Vue.config.keyCode.huiche=13 //不支持这样定义别名按键
④、移除v-on.native修饰符
父组件中绑定事件

<Child 
   v-on:close="handleClose"
   v-on:click="handleClick"
>
</Child>

子组件中声明自定义事件

export default{
  //如果不声明就是原生事件,声明了就是自定义事件
  emits:['close']
}

⑤、移除过滤器filter

相关文章

网友评论

    本文标题:vue3学习

    本文链接:https://www.haomeiwen.com/subject/dandkrtx.html