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>
相关推荐
狂炫一碗大米饭1 小时前
如何优化vue中的渲染🔒🔑🔓
vue.js
歪歪1001 小时前
Vue原理与高级开发技巧详解
开发语言·前端·javascript·vue.js·前端框架·集成学习
用户6757049885023 小时前
一文吃透 Promise 与 async/await,异步编程也能如此简单!建议收藏!
前端·javascript·vue.js
summer7774 小时前
开箱即用的openlayer地图效果
前端·javascript·vue.js
三小河4 小时前
详解React.memo的更新机制
前端·javascript·vue.js
张志鹏PHP全栈4 小时前
Vue第十四天,Vue3路由(第一部分)
前端·vue.js
李长鸿4 小时前
vue3路由基础
vue.js
wycode4 小时前
Vue2源码笔记(2)编译时-模板代码是怎么生效的之从AST生成渲染代码
前端·vue.js
袋鱼不重4 小时前
手把手搭建Vue轮子从0到1:6. Computed 源码解读
前端·vue.js·面试