Vue3学习

1. 配置环境

1.1. 安装nodejs(建议安装14版本稳定)

下载|Nodejs官网
装好之后可以使用以下命令进行查看,来确定是否安装成功
image

1.2. 构建vite项目

官方文档

1.2.1 使用vite初始化一个项目

npm

   npm init vite@latest

yarn

   yarn create vite

运行之后,跟着提示走就好(项目名称、项目模板......)

1.3 安装vue cli 脚手架

npm install @vue/cli -g 进行脚手架安装
vue -V 检查是否安装成功
vue create 项目名称 进行项目创建

1.4 VSCode 插件

  • Vue Language Features(Volar)
  • TypeScript Vue Plugin (Volar)

1.5 安装less

在项目路径下使用如下命令进行安装

npm install less less-loader

2. Vite目录&Vue单文件组件

2.1. Vite目录

public 下面的不会被编译,可以存放静态资源
assets 下面可以存放可编译的静态资源
components 下面用来我们的组件
App.Vue 是全局组件
main.ts 全局的ts文件
index.html 非常重要的入口文件(webpack,rollup他们的入口文件都是enrty input是一个js文件而Vite的入口文件是一个html文件,他刚开始不会编译这些js文件,只有当你用到的时候 如 script src="xxxx.js"会发起一个请求被vite拦截这时候才会解析js文件)
vite.config.ts 这是vite的配置文件具体配置项

2.2 SFC语法规范

.vue都由三种类型的顶层语法块所组成:<template>、<script>、<style>

  • <template>
    • 每个*.vue文件最多可同时包含一个顶层<template>块
    • 其中的内容会被提取出来传递给@vue/compiler-dom,预编译为JavaScript的渲染函数,并附属到导出的组件上作为其render选项

  • <script>
    • 每一个*.vue文件最多可同时包含一个<script>块(不包括<script setup>)
    • 该脚本将作为ES Module来执行
    • 其默认导出的内容应该是Vue组件选项对象,它要么是一个普通对象,要么是defineComponent的返回值

  • <script setup>
    • 一个*.vue文件最多可同时包含一个<script setup>块(不包括常规的<script>)
    • 该脚本会被处理并作为组件的setup()函数使用,也就是说它会在每个组件实例中执行。<script setup>的顶层版绑定会自动暴露给模板

  • <style>
    • 一个*.vue文件最多可同时包含多个<style>标签
    • <style>标签可以通过scoped和module将样式封装在当前组件中。多个不同封装模式的<style>标签可以在同一个组件中混用

3. 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 修饰符 (冒泡)

4. ref全家桶

4.1 ref

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

<template>
  <div>
    <button @click="changeMsg">change</button>
    {{message}}
  </div>
</template>

<script setup lang="ts">
import {ref,Ref} from 'vue';

// let message:Ref<string>=ref('hello')
let message=ref<string|number>('hello')
const changeMsg=()=>{
  message.value="你好"
}
</script>

<style scoped>
</style>

4.2 isRef

判断是不是一个ref对象

<script setup lang="ts">
import {isRef, ref,Ref} from 'vue';

let message:Ref<string>=ref('hello')
let notRef:number=123
const changeMsg=()=>{
  message.value="你好"
  // isRef() 判断是不是一个ref对象
  console.log(isRef(message)) //true
  console.log(isRef(notRef)) //false
}
</script>

4.3 shallowRef

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

<script setup lang="ts">
import {shallowRef} from 'vue';

let message=shallowRef({
  name:'hello'
})
const changeMsg=()=>{
  // message.value.name='你好' //无法响应式改变值
  // console.log(message)
  message.value={name:'你好'} //可以动态响应
}
</script>

4.4 triggerRef

强制更新页面DOM

<script setup lang="ts">
import {shallowRef, triggerRef} from 'vue';

let message=shallowRef({
  name:'hello'
})
const changeMsg=()=>{
  message.value.name='你好' //无法响应式改变值
  triggerRef(message) //强制更新dom
}
</script>

4.5 customRef

自定义ref

5. Reactive 全家桶

5.1 reactive

用来绑定复杂的数据类型,例如 对象、数组,绑定普通的数据类型可以使用ref

<template>
  <div>
    <button @click="changeMsg">change</button>
    {{person.name}}
  </div>
</template>

<script setup lang="ts">
import {reactive} from 'vue';

let person=reactive({
  name:'zs'
})

const changeMsg=()=>{
  person.name="张三"
}
</script>

<style scoped>
</style>

5.2 readonly

拷贝一份proxy对象将其设置为只读

<script setup lang="ts">
import {reactive,readonly} from 'vue';

let person=reactive({
  name:'zs'
})

let copy=readonly(person) 
const changeMsg=()=>{
  copy.name='张三' //无法赋值,只读的 (浏览器控制台输出警告)
}
</script>

<style scoped>

5.3 shallowReactive

只能怼浅层的数据,如果是深层的数据只会改变值,不会改变视图

<template>
  <div>
    <button @click="changeMsgname">changename</button>
    <button @click="changeMsgshow">changeshow</button>
    {{person}}
  </div>
</template>

<script setup lang="ts">
import {shallowReactive} from 'vue';

let person=shallowReactive({
  name:'zs',
  test:{
    test2:{
      show:'test_test2:show'
    }
  }
})


const changeMsgname=()=>{
  person.name="张三"
}
const changeMsgshow=()=>{
  person.test.test2.show="test_test2_显示" //这里修改,知识值会变,显示不变
  console.log(person)
}
</script>

<style scoped>
</style>

6 to系列全家桶

6.1 toRef

如果原始对象是非响应式的就不会更新视图,数据是会变的

<template>
  <div>
    <button @click="change">change</button>
    {{state}}
  </div>
</template>
<script setup lang="ts">
import {toRef,reactive} from 'vue';

// const obj={
//   foo:1,
//   bar:1
// }

const obj=reactive({
  foo:1,
  bar:1
}) //添加reactive后进行操作,页面显示会改变
const state=toRef(obj,'bar')
const change=()=>{
  state.value++
  console.log('原始对象',obj);
  console.log('引用对象',state);
}
</script>
<style scoped>
</style>

6.2 toRefs

可以帮我们批量创建ref对象主要是方便我们解构使用

<template>
  <div>
    <button @click="change">change</button>
    foo---{{foo}}
    bar--{{bar}}
  </div>
</template> 
<script setup lang="ts">
import {toRefs,reactive} from 'vue';

let obj=reactive({
  foo:1,
  bar:1
}) //添加reactive后进行操作,页面显示会改变
let {foo,bar}=toRefs(obj)
console.log(foo,bar);
const change=()=>{
  foo.value++
  bar.value++
  console.log(foo,bar);
}
</script>\
<style scoped>
</style>

6.3 toRaw

将响应式对象转化为普通对象

<template>
  <div>
  </div>
</template>
<script setup lang="ts">
import {toRaw,reactive} from 'vue';
let obj=reactive({
  foo:1,
  bar:1
}) //添加reactive后进行操作,页面显示会改变
const raw=toRaw(obj) //将响应式对象变为原始对象
console.log('响应式的',obj);
console.log('raw',raw);
</script>
<style scoped>
</style>

7 computed计算属性

用法

计算属性就说当依赖的属性的值发生变化的时候,才会触发它的改变,如果依赖的值,不发生变化的时候,使用的是缓存中的属性值

<template>
  <div>
    <input type="text" v-model="firstname">
    <input type="text" v-model="lastname">
    {{firstname}} --{{lastname}}
    {{name}}
  </div>
</template>
<script setup lang="ts">
import {ref,computed} from 'vue';
let firstname=ref('')
let lastname=ref('')
// 函数形式
// const name=computed(()=>{
//   return firstname.value+'---'+lastname.value
// })
// 对象形式
const name=computed({
  get(){
    return firstname.value+lastname.value
  },
  set(){
    firstname.value+lastname.value
  }
})
</script>
<style scoped>
</style>

8. watch侦听器

watch需要侦听特定的数据源,并在单独的回调函数中执行
watch第一个参数监听源
watch第二个参数回调函数cb(newValue,oleValue)
watch第三个参数一个options配置项是一个对象{
immediate:true //是否立即调用一次
deep:true 是否开启深度监听
}

<template>
  <div>
    <!-- <input type="text" v-model="obj.nar.bar.name" /> -->
    <!-- <input type="text" v-model="message2"> -->

    <input type="text" v-model="obj.name" />
    <input type="text" v-model="obj.age" />
  </div>
</template>

<script setup lang="ts">
import { ref, watch, reactive } from "vue";
// let message = ref<string>("");
// let message2 = ref<string>("");
// 监听一个值
// watch(message,(newVal,oldVal)=>{
//   console.log('新值',newVal);
//   console.log('旧值',oldVal);
// })
//监听多个值
// watch([message, message2], (newval, oldval) => {
//   console.log("新值", newval);
//   console.log("旧值", oldval);
// });
// 监听对象(深度监听,有bug新旧值一样)
// let obj=ref({
//   nar:{
//     bar:{
//       name:'zs'
//     }
//   }
// })
// watch(obj,(newval,oldval)=>{
//   console.log('新的',newval);
//   console.log('旧的',oldval);
// },{
//   deep:true
// })

//监听对象(监听reactive,可以不配置deep也可以深度监听,新旧值一样)
// let obj=reactive({
//   nar:{
//     bar:{
//       name:'zs'
//     }
//   }
// })
// watch(obj,(newval,oldval)=>{
//   console.log('新的',newval);
//   console.log('旧的',oldval);
// })

//监听对象单一值
let obj = reactive({
  name: "zs",
  age: 18,
});

watch(
  () => obj.name,
  (newval, oldval) => {
    console.log("新值", newval);
    console.log("旧值", oldval);
  }
);
</script>
<style scoped></style>

9 watchEffect高级侦听器

立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该行数
如果用到message就只会监听message,就是用到几个监听几个,而且是非惰性,会默认调用一次

<template>
  <div>
    <input type="text" v-model="message" /> 
    <input type="text" v-model="message2">
  </div>
</template>

<script setup lang="ts">
import { ref,watchEffect } from "vue";
let message=ref<string>('大猫')
let message2=ref<string>('大狗')
watchEffect(()=>{
  console.log('message---',message.value);
})
</script>
<style scoped></style>

清楚副作用

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

<template>
  <div>
    <input type="text" v-model="message" /> 
    <input type="text" v-model="message2">
  </div>
</template>

<script setup lang="ts">
import { ref,watchEffect } from "vue";
let message=ref<string>('大猫')
let message2=ref<string>('大狗')
watchEffect((oninvalidate)=>{
  console.log('message---',message.value);
  oninvalidate(()=>{
    console.log("监听之前");
  })
})
</script>
<style scoped></style>

停止跟踪watchEffect返回一个函数,调用之后将停止监听

<template>
  <div>
    <input type="text" v-model="message" /> 
    <input type="text" v-model="message2">
    <button @click="stopwatch">停止</button>
  </div>
</template>

<script setup lang="ts">
import { ref,watchEffect } from "vue";
let message=ref<string>('大猫')
let message2=ref<string>('大狗')
const stop= watchEffect((oninvalidate)=>{
  console.log('message---',message.value);
  oninvalidate(()=>{
    console.log("监听之前");
  })
})
const stopwatch=(()=>{
  stop()
})
</script>
<style scoped></style>

10 组件生命周期

  1. onBeforeMount
    页面(组件)创建之前,页面的dom元素是无法读取到的
  2. onMounted
    页面(组件)创建完成,可以拿到dom元素
  3. onBeforeUpdate
    dom元素(组件)更新之前
  4. onUpdated
    dom元素(组件)更新之后
  5. onBeforeUnmount
    组件卸载之前
  6. onUnmounted
    组件卸载之后

11

posted @ 2022-07-15 17:44  风吹PP好凉爽  阅读(58)  评论(0编辑  收藏  举报