vue3的api解读-ref和reactive

news/2024/10/17 17:52:28/

目录

构造一个演示框架(VUE3)

/src/examples/Helloworld.tsx

/src/mytypes.d.ts

/src/main.ts

/src/App.tsx

/src/layout.css

/src/examples/RefExample.tsx

/src/examples/ReactiveExample.tsx

思考

Vue提供的Reactive模式和vue.observable有什么区别?


构造一个演示框架(VUE3)

  • vue-router
  • rollup-context

Reactivity API: Core | Vue.js

/src/examples/Helloworld.tsx

// import { createVNode, h } from "vue"
export const HelloWorld = () => {// return h("h1", ["Hello world!!!"])return <h1>Hello world!!!</h1>
}

/src/mytypes.d.ts

// import type只引入type,不会执行
import type { RouteRecordRaw } from "vue-router";
// 路由类型
type MyRouteType = RouteRecordRaw & {key: string
}

/src/main.ts

import { createApp } from 'vue'
import { createWebHashHistory, createRouter } from 'vue-router'
import App from './App'
import { MyRouteType } from './mytypes'
// rollup-context能力,webpack是没有的
// 框架是vite3
// 获取去所有的/examples下的.tsx【typescript + jsx】文件
const examples = import.meta.glob("./examples/**/*.tsx")
// 安一个vue-router@next
// npm add vue-router@next
const routes: MyRouteType[] = []
const examplePromises = Object.keys(examples).map(x => examples[x]).map(f => f())
// examplePromises全部解析好
Promise.all(examplePromises).then(list => {for (let module of list) {for (let key in module) {const Component = module[key]routes.push({path: "/" + key.toLocaleLowerCase(),key,component: Component})}}const router = createRouter({history: createWebHashHistory(),routes})// 把routes作为App的属性传过去const app = createApp(App, { routes })app.use(router)app.mount('#app')})

/src/App.tsx

import { RouterLink, RouterView } from "vue-router"
import { MyRouteType } from "./mytypes"
import "./layout.css"
export default (props: {routes: MyRouteType[]
}) => {return <><header><h2>项目实战例子哟</h2></header><div class="body"><ul class="menu">{props.routes.map(x => {return <li key={x.key}><RouterLink to={x.path}>{x.key}</RouterLink></li>})}</ul><div class="content"><RouterView /></div></div></>
}

/src/layout.css

* {margin : 0;
}
html, body {height : 100%;
}
#app {height: 100%;
}
header {height : 60px;line-height: 60px;padding-left: 20px;width : 100%;background-color: black;color : white;
}
.body {display: flex;width : 100%;height : 100%;
}
.menu {padding-top : 20px;width : 200px;border-right:  1px solid #f2f3f4;min-height: 100%;
}
.menu li a{text-decoration: none;color : #2377de;
}
.menu li a:visited {text-decoration: none;color : #2377de;
}
.menu li {list-style: none;
}
.content {margin : 10px;position: relative;
}

/src/examples/RefExample.tsx

import { defineComponent, PropType, Ref, ref } from "vue";
// 使用响应式的值,通过defineComponent创建,
// 不用响应式的值的话 RefExample01 = ()= { return <div>2233</div> }
// 不使用defineComponent就没有setup()可以用
export const RefExample01 = defineComponent({setup() {// ref是个代理,通过.value获取值const count = ref(0)console.log('setup函数只执行一次')// 渲染函数return () => {console.log('render函数每次都执行')return (<div><button onClick={() => {count.value++}}>+</button>{count.value}</div>)}}
})
export const RefExample02 = defineComponent({setup() {// ref是个代理,通过.value获取值const count = ref(0)console.log('setup函数只执行一次')// 渲染函数return () => {console.log('render函数每次都执行')return (<div><button onClick={() => {count.value++}}>+</button></div>)}}
})
export const RefExample03 = defineComponent({setup() {// ref是个代理,通过.value获取值const count = ref(0)console.log('setup函数只执行一次')// 渲染函数return () => {return (<div><button onClick={() => {count.value++}}>+</button><Count1 count={count} /><Counter count={count} /></div>)}}
})
const Counter = ({ count }: {count: Ref<number>
}) => {return <div>{count.value}</div>
}
const Count1 = defineComponent({props: { // 需要映射属性count: {type: Object as PropType<Ref<number>>, // 给一个别名typerequired: true // 写上这个,vue可以让你在render里拿到值}},setup(props) {return (// 这样写也能拿到值// props: {//   count: Ref<number>// }) => {return <div>{props.count.value}</div>}}
})

/src/examples/ReactiveExample.tsx

import {customRef,defineComponent,reactive,toRefs,unref,isRef,
} from "vue";
// https://v3.vuejs.org/api/refs-api.html
export const ReactiveExample01 = defineComponent({setup() {const state = reactive({a: "123",b: 2})setTimeout(() => {state.a = "456"}, 1000)setTimeout(() => {state.b = 100}, 2000)return () => {return <div><div>{state.a}</div><div>{state.b}</div></div>}}
})
function getState() {const state = reactive({a: "123",b: 2})return toRefs(state)
}
export const ReactiveExample02 = defineComponent({setup() {const { a, b } = getState()// const { a, b } = toRefs(state) // 批量refsetTimeout(() => {// state.a = "456" // reactive使用法a.value = "456" // ref使用法}, 1000)setTimeout(() => {// state.b = 100b.value = 100}, 2000)return () => {return <div><div>{a.value}</div><div>{b.value}</div></div>}}
})
// 防抖的customRef
function useDebouncedRef(value: string, delay = 200) {let timeout: number | undefinedreturn customRef((track: () => void, trigger: () => void) => {return {get() {track()return value},set(newValue: any) {clearTimeout(timeout)timeout = setTimeout(() => {value = newValuetrigger()}, delay)}}})
}
export default {setup() {return {text: useDebouncedRef('hello')}}
}

思考

  • 是什么依赖Reactive值? 是我们的渲染在依赖它们
  • 为什么不显式指定Reactive值的依赖?

拥抱函数式,没有办法显式的提供依赖,我们不确定值,setup时候知道,但是render渲染时候,没有办法给它依赖了

Vue提供的Reactive模式和vue.observable有什么区别?

const state = Vue.observable({ count: 0 })
const Demo = {render(h) {return h('button', {on: { click: () => { state.count++ }}        }, `count is: ${state.count}`)    }
}

区别在于函数式

  • 什么是Observable? 可以被观察的东西每个 ref()的值
  • Reactive === Observable ?

Reactive【响应式,这个组件,这个值,在任何时候,像人一样,有主动思维,知道怎么响应外部的环境,知道怎么去做】

Observable【设计模式,架构手段,就是去观察可以被观察的东西】


http://www.ppmy.cn/news/103979.html

相关文章

机器学习 监督学习 Week2

Lib01 多变量线性回归 依旧是房价预测&#xff0c;但这次引入了多个变量&#xff0c;不仅仅只有房屋面积影响着房价&#xff0c;依旧尝试使用梯度下降算法找到最优的【w,b】&#xff0c;并且习惯使用向量点乘运算提高效率 import copy, math import numpy as np import matplot…

C++入门--初步认识类和对象

0.前言 前面几章&#xff0c;我们一起学习了C和C语言的不同之处&#xff0c;已经算是半只脚迈入了C的“门槛”&#xff0c;本章让我们继续学习C的类和对象。 1.面向对过程和面向对象的初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&…

一个拦截XSSI 识别Web蜜罐的插件

说明 这是一个带有学习和研究性质的Chrome扩展程序。 功能 截获页面中发起的XSSI请求&#xff0c;通过域名、URI、Query黑名单特征识别阻断可疑的XSSI&#xff08;Jsonp Callback、XSS等&#xff09; 对可疑URL进行深度检测&#xff0c;通过发送请求获取body内容&#xff0c…

windwos 安装 pysqlcipher3

windwos 安装 pysqlcipher3 安装软件 参考别人的文章&#xff0c;有的要安装Tcl Windows(64-bit, x64)&#xff0c;下载地址 但是我没有安装也可以用 安装python 推荐安装 python3.7 日常使用够了&#xff0c;不要追求新出来的版本&#xff0c;不太完善。 安装visual studio…

Postman 接口测试神器

Postman 接口测试神器 Postman 是一个接口测试和 http 请求的神器&#xff0c;非常好用。 官方 github 地址: Postman Inc. GitHub Postman 的优点&#xff1a; 支持各种的请求类型: get、post、put、patch、delete 等支持在线存储数据&#xff0c;通过账号就可以进行迁移…

MySQL数据库安全与备份

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;MySQL &#x1f96d;本文内容&a…

无屏幕实现连接树莓派

无屏幕实现连接树莓派 欢迎来到我的博客&#xff01;今天我将与大家分享如何无需使用屏幕&#xff0c;实现与树莓派的连接。对于那些在树莓派项目中不方便使用屏幕的人来说&#xff0c;这将是一个有用的技巧。 材料清单 在开始之前&#xff0c;让我们先准备好所需的材料&…

C++ Primer第五版_第十八章习题答案(21~30)

文章目录 练习18.21练习18.22练习18.23练习18.24练习18.25练习18.26练习18.27练习18.28练习18.29练习18.30 练习18.21 解释下列声明的含义&#xff0c;在它们当作存在错误吗&#xff1f;如果有&#xff0c;请指出来并说明错误的原因。 (a) class CADVehicle : public CAD, Vehi…