关于Vue3+pinia+ts的学习笔记

Vue的模板语法:

v- 开头都是vue 的指令

v-text 用来显示文本

v-html 用来展示富文本

v-if 用来控制元素的显示隐藏(切换真假DOM)

v-else-if 表示 v-if 的“else if 块”。可以链式调用

v-else v-if条件收尾语句

v-show 用来控制元素的显示隐藏(display none block Css切换)

v-on 简写@ 用来给元素添加事件

v-bind 简写:  用来绑定元素的属性Attr

v-model 双向绑定

v-for 用来遍历元素

v-on修饰符 冒泡案例
//v-bind 绑定class 案例 1


 
 

 
 
 
//v-bind 绑定class 案例 2

 


 
 
 
//v-bind 绑定style案例

 
 
 

 
 
//v-model 案例

 
 

 
 
 

________________________________分段_______________________________________

Vue——ref

接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。

//我们这样操作是无法改变message  的值 应为message 不是响应式的无法被vue 跟踪要改成ref

 
 
 

 
 

 改为ref

//Ref TS对应的接口
interface Ref {
  value: T
}

 注意被ref包装之后需要.value 来进行赋值!!!!!
 


 
 
 

 
 

//--------------------------------ts两种方式

 
 
 

 
 

 isRef

 判断是不是一个ref对象

import { ref, Ref,isRef } from 'vue'
let message: Ref = ref("我是message")
let notRef:number = 123
const changeMsg = () => {
  message.value = "change msg"
  console.log(isRef(message)); //true
  console.log(isRef(notRef)); //false
  
}

shallowRef

创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的

例子

修改其属性是非响应式的这样是不会改变的


 
 
 

 
 

 例子2

这样是可以被监听到的修改value

import { Ref, shallowRef } from 'vue'
type Obj = {
  name: string
}
let message: Ref = shallowRef({
  name: "小满"
})
 
const changeMsg = () => {
  message.value = { name: "大满" }
}

triggerRef 

强制更新页面DOM

这样也是可以改变值的


 
 
 
 
 
 

customRef

自定义ref 

customRef 是个工厂函数要求我们返回一个对象 并且实现 get 和 set

 

________________________________分段_______________________________________

diff算法:

关于我的个人理解,diff算法不是用暴力算法来解决DOM的相同或者不相同

特点 :

 (1.)  diff 算法就是将两个新旧的虚拟 DOM 进行对比并且返回一个 patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。

diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁

(2.) 比较只会在同层级别进行,不会跨层级比较。

关于Vue3+pinia+ts的学习笔记_第1张图片

 (3.) 在 diff 比较 过程汇总,循环从两边向中间比较。

关于Vue3+pinia+ts的学习笔记_第2张图片

(4.) diff 算法的步骤:

  1、用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文 档当中
2、当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较(diff),记录两棵树差异
3、把第二棵树所记录的差异应用到第一棵树所构建的真正的DOM树上(patch),视图就更新了

________________________________分段_______________________________________

组件基础

每一个.vue 文件呢都可以充当组件来使用

每一个组件都可以复用

关于Vue3+pinia+ts的学习笔记_第3张图片

 例如 helloWorld 充当子组件

关于Vue3+pinia+ts的学习笔记_第4张图片

 父组件使用

引入子组件 helloWorld 然后直接就可以去当标签去使用 (切记组件名称不能与html元素标签名称一样)

关于Vue3+pinia+ts的学习笔记_第5张图片

组件的生命周期

简单来说就是一个组件从创建 到 销毁的 过程 成为生命周期

在我们使用Vue3 组合式API 是没有 beforeCreate 和 created 这两个生命周期的

 关于Vue3+pinia+ts的学习笔记_第6张图片

onBeforeMount()

在组件DOM实际渲染安装之前调用。在这一步中,根元素还不存在。

onMounted()

在组件的第一次渲染后调用,该元素现在可用,允许直接DOM访问。

onBeforeUpdate()

数据更新时调用,发生在虚拟 DOM 打补丁之前。

updated()

DOM更新后,updated的方法即会调用。

onBeforeUnmount()

在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。

onUnmounted()

卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

选项式 API Hook inside setup
beforeCreate Not needed*
created Not needed*
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
errorCaptured onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered
activated onActivated
deactivated onDeactivated

配置全局组件

例如组件使用频率非常高(table,Input,button,等)这些组件 几乎每个页面都在使用便可以封装成全局组件

案例------我这儿封装一个Card组件想在任何地方去使用↓


 

 

卡片效果:

关于Vue3+pinia+ts的学习笔记_第7张图片

 使用方法:

在main.ts 引入我们的组件跟随在createApp(App) 后面 切记不能放到mount 后面这是一个链式调用用(使用的是vite脚手架)

其次调用 component 第一个参数组件名称 第二个参数组件实例

import { createApp } from 'vue'
import App from './App.vue'
import './assets/css/reset/index.less'
import Card from './components/Card/index.vue'
 
               //(调用↓):component
createApp(App).component('Card',Card).mount('#app')

↑这里Card全局组件就已经装载完毕了

Card组件的使用方法(直接在其他vue页面 立即使用即可 无需引入)↓

配置局部组件:


 

就是在一个组件内(A) 通过import 去引入别的组件(B) 称之为局部组件

应为B组件只能在A组件内使用 所以是局部组件

如果C组件想用B组件 就需要C组件也手动import 引入 B 组件

配置递归组件:

原理跟我们写js递归是一样的 自己调用自己 通过一个条件来结束递归 否则导致内存泄漏

案例递归树

在父组件配置数据结构 数组对象格式 传给子组件

type TreeList = {
  name: string;
  icon?: string;
  children?: TreeList[] | [];
};
const data = reactive([
  {
    name: "no.1",
    children: [
      {
        name: "no.1-1",
        children: [
          {
            name: "no.1-1-1",
          },
        ],
      },
    ],
  },
  {
    name: "no.2",
    children: [
      {
        name: "no.2-1",
      },
    ],
  },
  {
    name: "no.3",
  },
]);

子组件接收值 第一个script

type TreeList = {
  name: string;
  icon?: string;
  children?: TreeList[] | [];
};
 
type Props = {
  data?: T[] | [];
};
 
defineProps>();
 
const clickItem = (item: TreeList) => {
  console.log(item)
}

子组件增加一个script 定义组件名称为了 递归用 

template 

TreeItem 其实就是当前组件 通过import 把自身又引入了一遍 如果他没有children 了就结束

  
{{item.name}}

效果图如下↓

关于Vue3+pinia+ts的学习笔记_第8张图片

关于递归组件的使用完整说明:

(创建了[一个Index组件和一个Test组件还有一个View组件])

{   

(1)Index组件是放需要递归的假数据和引入Test组件还有传值给Test数据(父子组件传值)

(2)Test组件是接收了父组件的值也就是Index组件的值,重点:(如果想要递归一个不确定层级的树结构,就需要再一次引入本身这个组件也就是再一次引入Test这个组件

(3)View组件就只是一个视图而已

}

下面展示组件的详细代码:

Index组件:









Test组件:

重点:这里引入了本身也就是Test这个组件我给它起名叫:QuoteItself 后来我再使用了QuoteItself 这个组件(注意下方代码要牢记)







View组件:




异步组件:

如果我用yarn build进行打包关于Vue3+pinia+ts的学习笔记_第9张图片

 打包结果是这样的结构:

关于Vue3+pinia+ts的学习笔记_第10张图片

 这样vite会把所有的组件打包到一个js里这样是很消耗性能的。所谓异步组件就是把请求后台的异步任务封装成一个组件众,所周知的是如果请求后台数据会有可能因各种因素让后台数据无法展示到页面上,这样就会使页面出现白屏现象这样是很影响用户的用户体验。所以就需要把异步组件打包成另一个js;而不是像上面把所有组件都打包到一个js文件里面。

下面我将实现封装一个异步组件:

首先我需要创建一个假的后台接口我将它命名为data.json

关于Vue3+pinia+ts的学习笔记_第11张图片

 而后我要写一个接口去拿到这里的数据

type NameList = {
    name:String
}

export function Axios(url:string):Promise {
   return new Promise((resolve)=>{
     let xhr:XMLHttpRequest = new XMLHttpRequest()

     xhr.open('GET',url)

     xhr.onreadystatechange=function(){
        if(xhr.readyState === 4 && xhr.status === 200){
          setTimeout(() => {
            resolve(JSON.parse(xhr.responseText))
          }, 2000);
        } 
     }

     xhr.send(null)
   })
}

在我的项目目录下创建一个用于测试使用的 test-4.vue 组件

随后引入刚刚写的接口

再去读取刚刚data.json里的数据

关于Vue3+pinia+ts的学习笔记_第12张图片

 随后我们去浏览器观察才发现在网页里并没有展示出我们想要的数据

关于Vue3+pinia+ts的学习笔记_第13张图片

 其实没展示出来也是正确的我们现在已经把这个组件变成异步组件了

所以我们需要用Vue的defineAsyncComponent()函数封装一下还需要用Vue里内置组件来配合Test4的使用才能在页面上显示数据



页面大概就是以下的效果:

关于Vue3+pinia+ts的学习笔记_第14张图片

 当我再次使用yarn build打包之后:

关于Vue3+pinia+ts的学习笔记_第15张图片

 可以看到多了一个js文件这个文件就是我们分出来的异步组件

----------------------------------------------------------分段-----------------------------------------------------------------

watch侦听器

watch是能监听复杂的数据结构的,但是它会有个bug

 关于Vue3+pinia+ts的学习笔记_第16张图片

 

 关于Vue3+pinia+ts的学习笔记_第17张图片

现在我传入了一个复杂的数据结构

然后watch本身有第二个参数deep这是深度监听如果不传入第二个参数是不能监听复杂的数据结构

我没再来看看变化

关于Vue3+pinia+ts的学习笔记_第18张图片

 页面效果:关于Vue3+pinia+ts的学习笔记_第19张图片

 如果watch监听的是reactive的数据那么就不需要写第二个参数“deep”

watch的几种语法写法:

  (1)如果你想监听多个数据可以用数组的方式写列如:

let Test1 = ref('');


let Test2 = ref('');


watch([Test1,Test2 ], (newVal, oldVal) => {
  console.log('新的值----', newVal);
  console.log('旧的值----', oldVal);
})

(2)如果你想只监听一个数据结构可以用回调函数的方式写列如:

let data = reactive({
 name1:'<>',
 name2:'[]'
})

watch(()=>data.name1,(newVal, oldVal) => {
  console.log('新的值----', newVal);
  console.log('旧的值----', oldVal);
})

----------------------------------------------------------分段-----------------------------------------------------------------

认识watchEffect高级侦听器:

watchEffect

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

如果用到message 就只会监听message 就是用到几个监听几个 而且是非惰性 会默认调用一次

let message = ref('')
let message2 = ref('')
 watchEffect(() => {
    //console.log('message', message.value);
    console.log('message2', message2.value);
})

 清除副作用

就是在触发监听之前会调用一个函数可以处理你的逻辑例如防抖

import { watchEffect, ref } from 'vue'
let message = ref('')
let message2 = ref('')
 watchEffect((oninvalidate) => {
    //console.log('message', message.value);
    oninvalidate(()=>{
        
    })
//oninvalidate()里会比watchEffect函数里所有东西都提前调用
    console.log('message2', message2.value);
})

停止跟踪 watchEffect 返回一个函数 调用之后将停止更新

const stop =  watchEffect((oninvalidate) => {
    //console.log('message', message.value);
    oninvalidate(()=>{
 
    })
    console.log('message2', message2.value);
},{
    flush:"post",
    onTrigger () {
 
    }
})
stop()

更多的配置项

副作用刷新时机 flush 一般使用post

pre sync post
更新时机 组件更新前执行 强制效果始终同步触发 组件更新后执行

onTrigger  可以帮助我们调试 watchEffect

import { watchEffect, ref } from 'vue'
let message = ref('')
let message2 = ref('')
 watchEffect((oninvalidate) => {
    //console.log('message', message.value);
    oninvalidate(()=>{
 
    })
    console.log('message2', message2.value);
},{
    flush:"post",
    onTrigger () {
        
    }
})

----------------------------------------------------------分段-----------------------------------------------------------------

你可能感兴趣的:(学习,javascript,前端,typescript,vue)