vue3基础学习

toc

在html文件中引入vue

vue 复制代码
<body>
  <div id="app">
     <h1> {{ count }} </h1>
     <button @click="count++">count+1</button>
  </div>
  // type = module是必须要写的,因为要使用es6的import语法
  <script type="module">
      import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'        
      createApp({
        setup() {
          const count = ref(0)
          return {
            count
          }
        }
      }).mount("#app")
  </script>
</body>

脚手架

1,安装node环境之后,就会有npm命令 2,npm create vue@latest 3,安装文心快码插件

setup语法糖

vue 复制代码
<!-- 相当于写了setup函数并且return -->
<script setup lang="ts">
const name = 'hello'
</script>
<script lang="ts">
//  定义组件名称,可以不写,但是为了调试方便,建议写上
export default {
  name: 'App'
}
</script>
<template>
  <h1>{{name}}</h1>
</template>

计算属性

vue 复制代码
<script setup lang="ts">
import { computed, ref } from 'vue'
const name = ref('张三')
// 只读的computed,不能修改值
let fullname = computed(() => `${name.value} Lee`)
// 可读写的computed,可以修改值
let fullname2 = computed({
  get: () => `${name.value} Lee`,
  set: (val) => {
    console.log(val);
    name.value = val;
  },
})

function changeName() {
  fullname2.value = "李四 Lee"
}
</script>
 
<template>
  <input type="text" v-model="name">
  <h1>{{ fullname2 }}</h1>
  <button @click="changeName">change full name</button>
</template>

ref & reactive 定义对象类型响应式数据

ref的value响应式对象是reactive实现的

toRefs & toRef

将响应式对象中的每个属性转为ref对象

toRefs是批量转换

vue 复制代码
<script setup lang="ts">
import { reactive,toRef,toRefs } from 'vue'
const person = reactive({
  name: '张三',
  age: 18
})

// 解构出来 const {name,age} = person; name和age不是响应式的,person.name是响应式
// 所以修改name的值只是name的值变了,person.name的值不变
// 解决方法是使用toRefs或toRef, 将name转为响应式引用
// let name = toRef(person,'name')
let {name, age} = toRefs(person)
function changeName() {
  name.value += "~"
  console.log(name.value, person.name);
  // 张三~~~~~~~ 张三
}
</script>
 
<template>
  <h1>{{name}}</h1>
  <br>
  <button @click="changeName">change name</button>
</template>

watch监视

watch监视ref定义的基本类型数据

jsx 复制代码
const count = ref(0)
// watch 监听ref定义的数据源,当数据变化时执行回调函数, watchStop是停止监视的函数
const watchStop = watch(count, (newVal, old) => {
    console.log(newVal, old)
    if (newVal === 10) {
        // 停止监听
        watchStop()
    }
})

watch监视ref定义的对象类型数据

监视的是对象的地址值,要想监视个别属性变化,需要开启深度监视

vue 复制代码
<script setup lang="ts">
  import { ref, watch } from 'vue'
  let person = ref({
    name: 'zhangsan',
    age: 18
  })
  // changeName 并不会触发 watch 监听器
  function changeName() {
    person.value.name = 'lisi'
  }
  function changePerson() {
    // 会触发 watch 监听器 因为改变了整个对象引用
    person.value = {name: 'wangwu', age: 20} 
  }
  watch(person, (newVal, oldVal) => {
    console.log(newVal, oldVal)
  })
  // 总结:监视ref对象类型数据,监视的是对象的地址值,如果要监听对象内部属性的变化,需要使用深度监听。
  watch(person, (newVal, oldVal) => {
    console.log(newVal, oldVal)
  }, {deep: true})
</script>
 
<template>
  <h1>{{person.name}}</h1>
  <br>
  <button @click="changeName">change name</button>
  <button @click="changePerson">change person</button>
</template>

watch监视reactive定义的对象类型数据,默认开启了深度监视

vue 复制代码
<script setup lang="ts">
  import { watch, reactive } from 'vue'
  let person = reactive({
    name: 'zhangsan'
  })
  // watch 能深度监视对象内部属性的变化,且深度监视无法stop
  function changeName() {
    person.name += '~'
  }
  function changePerson() {
    Object.assign(person, { name: 'lisi' })
  }
  watch(person, (newValue, oldValue) => {
    console.log(newValue, oldValue)
  })
</script>
 
<template>
  <h1>{{person.name}}</h1>
  <br>
  <button @click="changeName">change name</button>
  <button @click="changePerson">change person</button>
</template>

watch监视对象类型数据中的某个属性

1,若属性不是对象类型,需要写成函数式

2,若属性是对象类型,可以直接写,建议写成函数式

vue 复制代码
<script setup lang="ts">
  import { watch, reactive } from 'vue'
  let person = reactive({
    name: 'zhangsan',
    hobby: {
      h1: '篮球',
      h2: '足球'
    }
  })
  // 这种方式监视所有属性变化,如果只想监视name的变化,可以使用监视函数的形式,监视支持getter、ref、reactive和他们的数组形式。
  // watch(person, (newVal, oldVal) => {
  //   console.log('newVal', newVal, oldVal)
  // })
  // 函数式,这样就只监视name的变化了。如果要监视多个属性,可以使用数组的形式。
  // 监视响应式对象中的基本类型,要写成函数式
  // watch(() => person.name, (newVal, oldVal) => {
  //   console.log('getter', newVal, oldVal)
  // })

  // 这样能监视hobby单个h1、h2的变化,但是不能监视hobby对象本身的变化
  // watch(person.hobby, (newVal, oldVal) => {
  //   console.log('hobby:', newVal, oldVal)
  // })
  // 如果要监视hobby对象本身的变化,需要写成函数式。但是这样监视不到h1、h2的变化。如果要监视到,可以deep监视。
  watch(() => person.hobby, (newVal, oldVal) => {
    console.log('hobby:', newVal, oldVal)
  })

</script>
 
<template>
  <h1>姓名:{{person.name}}</h1>
  <h2>爱好:{{ person.hobby.h1 }}、{{ person.hobby.h2 }}</h2>
  <br>
  <button @click="person.name = 'lisi'">修改姓名</button>
  <button @click="person.hobby.h1 += '~'">修改h1</button>
  <button @click="person.hobby.h2 += '='">修改h2</button>
  <button @click="person.hobby = {h1: '悠悠球', h2: '乒乓球'}">修改hobby</button>
</template>

watch监视多个数据

vue 复制代码
<template>
  <h1>{{person.name}}</h1>
  <h1>{{person.age}}</h1>
  <h1>{{person.hobbies}}</h1>
  <h1>{{person.car}}</h1>
  <button @click="changeName">change name</button>
  <button @click="changeCar">change car</button>
</template>

<script lang="ts" setup>
 import { reactive, ref, watch } from 'vue'
 let person = reactive({
  name: '张三',
  age: 18,
  hobbies: ['抽烟', '喝酒', '烫头'],
  car: {
    c1: '奔驰',
    c2: '宝马'
  }
 })
 function changeName() {
  person.name = '李四'
 }
 function changeCar() {
    person.car.c1 = '特斯拉'
 }
// 结合前几种情况,如果要同时监听多个响应式对象的变化,可以使用数组的形式
 watch([()=>person.name, ()=>person.car.c1], (value) => {
  console.log(value);
 })
</script>

watchEffect全监视

vue 复制代码
<template>
  <h1>temp>60 | height>80时,触发监视</h1>
  <h1>{{ temp }}</h1>
  <h1>{{ height }}</h1>
  <button @click="changeTemp">change temp</button>
  <button @click="changeHeight">change height</button>
</template>

<script lang="ts" setup>
import { ref, watch, watchEffect } from "vue";
let temp = ref(10);
let height = ref(0);
function changeTemp() {
  temp.value += 10;
}
function changeHeight() {
  height.value += 10;
}
// 明确指出需要监视的属性,监视多个响应式引用时使用数组格式
watch([temp, height], ([t, h]) => {
  if (t > 60 && h > 80) {
    console.log("触发监视watch");
  }
});
watchEffect(() => {
  // 页面启动就触发监视,依赖发生变化时也会触发监视
  console.log("触发watchEffect监视");
  if (temp.value > 60 && height.value > 80) {
    console.log("触发监视watchEffect");
  }
});
</script>

标签的ref属性

ref放到普通html标签上

下面的代码,正常会输出 <h2>甄子丹</h2>

vue 复制代码
<template>
  <h1>李小龙</h1>
  <h2>甄子丹</h2>
  <button @click="changeH2">点我输出h2元素</button>
</template>

<script lang="ts" setup>
  function changeH2(){
    console.log(document.querySelector('h2'))
  }
</script>

但如果index.html里面是这样的

html 复制代码
 <body>
    <h2>李长鸿</h2>
    <div id="app">
    </div>
    <script type="module" src="/src/main.js"></script>
 </body>

那么获取到的h2就是<h2>李长鸿</h2>

不同文件中或不同组件中如果元素一样,使用js方式获取到的元素无法明确区分,包括通过id取元素,如果id不同文件中有重复就无法区分

vue 复制代码
<template>
  <h1>李小龙</h1>
  <h2 id="title2">甄子丹</h2>
  <button @click="changeH2">点我输出h2元素</button>
</template>

<script lang="ts" setup>
  function changeH2(){
    console.log(document.getElementById('title2'))
  }
</script>

解决这个问题就是使用ref,这样会不同文件相互隔离,互不影响

vue 复制代码
<template>
  <h1>李小龙</h1>
  <h2 ref="title2">甄子丹</h2>
  <button @click="changeH2">点我输出h2元素</button>
</template>

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

let title2 = ref();

function changeH2() {
  console.log(title2.value);
}
</script>

ref放到组件上

ref拿到的是组件实例,如果想打印出组件里面的属性,需要使用defineExpose

vue 复制代码
<template>
  <Person ref="ren">  </Person>
  <button @click="changePerson">点我输出person元素</button>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import Person from "@/components/Person.vue";

// 创建一个title2的响应式引用,用于存储ref标记的h2元素
let ren = ref();

function changePerson() {
  // 输出的是标签实例的引用,而非DOM元素,但是输出的内容看不到person里的属性,因为它是组件实例对象
  console.log(ren.value);
}
</script>

Person.vue组件

vue 复制代码
<template>
     <h2 class="person">{{name}}</h2>
</template>

<script lang="ts">
export default {
    name: 'Person',
}
</script>  

<script lang="ts" setup>
import { ref, defineExpose } from "vue";
  const name = ref("张三");
  defineExpose({name})
</script>

局部样式

元素内容属性 data-xxx就是局部样式,主要是style样式加了scope引起,<style scoped>

html 复制代码
<h2 data-v-7a7a37b1="">甄子丹</h2>
相关推荐
Sheldon一蓑烟雨任平生9 小时前
Vue3 依赖注入(provide 和 inject)
vue.js·inject·provide·vue3 依赖注入·跨级别组件通信
paopaokaka_luck11 小时前
基于SpringBoot+Vue的助农扶贫平台(AI问答、WebSocket实时聊天、快递物流API、协同过滤算法、Echarts图形化分析、分享链接到微博)
java·vue.js·spring boot·后端·websocket·spring
Sheldon一蓑烟雨任平生12 小时前
Vue3 重构待办事项(主要练习组件化)
vue.js·重构·vue3·组件化练习
zuo-yiran16 小时前
vue div标签可输入状态下实现数据双向绑定
前端·javascript·vue.js
qq_3168377516 小时前
使用leader-line-vue 时垂直元素间距过小连线打转的解决
前端·javascript·vue.js
abiao198116 小时前
VUE的“单向数据绑定” 和 “双向数据绑定”
前端·javascript·vue.js
麦麦大数据17 小时前
F042 A星算法课程推荐(A*算法) | 课程知识图谱|课程推荐vue+flask+neo4j B/S架构前后端分离|课程知识图谱构造
vue.js·算法·知识图谱·neo4j·a星算法·路径推荐·课程推荐
拉不动的猪17 小时前
多窗口数据实时同步常规方案举例
前端·javascript·vue.js
南清的coding日记18 小时前
Java 程序员的 Vue 指南 - Vue 万字速览(01)
java·开发语言·前端·javascript·vue.js·css3·html5
Xiaouuuuua18 小时前
2026年计算机毕业设计项目合集
前端·vue.js·课程设计