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>
相关推荐
q***38511 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端
喵个咪1 小时前
go-kratos-admin 快速上手指南:从环境搭建到启动服务(Windows/macOS/Linux 通用)
vue.js·go
用户841794814562 小时前
vxe-gantt table 甘特图如何设置任务视图每一行的背景色
vue.js
小章鱼学前端2 小时前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
涔溪2 小时前
实现将 Vue3 项目作为子应用,通过无界(Wujie)微前端框架接入到 Vue2 主应用中(Vue2 为主应用,Vue3 为子应用)
vue.js·前端框架·wujie
源码技术栈5 小时前
什么是云门诊系统、云诊所系统?
java·vue.js·spring boot·源码·门诊·云门诊
lcc1875 小时前
Vue3 ref函数和reactive函数
前端·vue.js
艾小码5 小时前
还在为组件通信头疼?defineExpose让你彻底告别传值烦恼
前端·javascript·vue.js
带只拖鞋去流浪5 小时前
迎接2026,重新认识Vue CLI (v5.x)
前端·vue.js·webpack
Coder-coco5 小时前
游戏助手|游戏攻略|基于SprinBoot+vue的游戏攻略系统小程序(源码+数据库+文档)
java·vue.js·spring boot·游戏·小程序·论文·游戏助手