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
12323
//v-bind 绑定class 案例 2
{{flag}}
//v-bind 绑定style案例
2222
//v-model 案例
{{ message }}
________________________________分段_______________________________________
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value
property,指向该内部值。
//我们这样操作是无法改变message 的值 应为message 不是响应式的无法被vue 跟踪要改成ref
{{ message }}
改为ref
//Ref TS对应的接口
interface Ref {
value: T
}
注意被ref包装之后需要.value 来进行赋值!!!!!
{{ message }}
//--------------------------------ts两种方式
{{ message }}
isRef
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,但不会使其值也变成响应式的
例子
修改其属性是非响应式的这样是不会改变的
{{ message }}
例子2
这样是可以被监听到的修改value
import { Ref, shallowRef } from 'vue'
type Obj = {
name: string
}
let message: Ref = shallowRef({
name: "小满"
})
const changeMsg = () => {
message.value = { name: "大满" }
}
强制更新页面DOM
这样也是可以改变值的
{{ message }}
自定义ref
customRef 是个工厂函数要求我们返回一个对象 并且实现 get 和 set
关于我的个人理解,diff算法不是用暴力算法来解决DOM的相同或者不相同
1、用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文 档当中
2、当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较(diff),记录两棵树差异
3、把第二棵树所记录的差异应用到第一棵树所构建的真正的DOM树上(patch),视图就更新了
________________________________分段_______________________________________
每一个.vue 文件呢都可以充当组件来使用
每一个组件都可以复用
例如 helloWorld 充当子组件
父组件使用
引入子组件 helloWorld 然后直接就可以去当标签去使用 (切记组件名称不能与html元素标签名称一样)
简单来说就是一个组件从创建 到 销毁的 过程 成为生命周期
在我们使用Vue3 组合式API 是没有 beforeCreate 和 created 这两个生命周期的
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组件想在任何地方去使用↓
标题
副标题
{{content}}
在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}}
效果图如下↓
(创建了[一个Index组件和一个Test组件还有一个View组件])
{
(1)Index组件是放需要递归的假数据和引入Test组件还有传值给Test数据(父子组件传值)
(2)Test组件是接收了父组件的值也就是Index组件的值,重点:(如果想要递归一个不确定层级的树结构,就需要再一次引入本身这个组件也就是再一次引入Test这个组件)
(3)View组件就只是一个视图而已
}
重点:这里引入了本身也就是Test这个组件我给它起名叫:QuoteItself 后来我再使用了QuoteItself 这个组件(注意下方代码要牢记)
{{item.name}}
打包结果是这样的结构:
这样vite会把所有的组件打包到一个js里这样是很消耗性能的。所谓异步组件就是把请求后台的异步任务封装成一个组件众,所周知的是如果请求后台数据会有可能因各种因素让后台数据无法展示到页面上,这样就会使页面出现白屏现象这样是很影响用户的用户体验。所以就需要把异步组件打包成另一个js;而不是像上面把所有组件都打包到一个js文件里面。
首先我需要创建一个假的后台接口我将它命名为data.json
而后我要写一个接口去拿到这里的数据
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里的数据
随后我们去浏览器观察才发现在网页里并没有展示出我们想要的数据
其实没展示出来也是正确的我们现在已经把这个组件变成异步组件了
所以我们需要用Vue的defineAsyncComponent()函数封装一下还需要用Vue里内置组件
菜单区域
loading...
页面大概就是以下的效果:
当我再次使用yarn build打包之后:
可以看到多了一个js文件这个文件就是我们分出来的异步组件
----------------------------------------------------------分段-----------------------------------------------------------------
watch是能监听复杂的数据结构的,但是它会有个bug
现在我传入了一个复杂的数据结构
然后watch本身有第二个参数deep这是深度监听如果不传入第二个参数是不能监听复杂的数据结构
我没再来看看变化
如果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
立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
如果用到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()
更多的配置项
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 () {
}
})
----------------------------------------------------------分段-----------------------------------------------------------------