一些Vue3知识点整理

265 阅读1分钟

Vue3知识点


1.双向数据绑定

掌握实现双向数据绑定的方式

1.1实现表单双向数据绑定

什么是双向数据绑定呢?

双向数据绑定指的是数据和视图,双向数据绑是数据和视图绑定,数据变化同步视图,视图要是更改了数据,就要同步给数据源

那么如何实现双向绑定?

<template>
  <input type="text" v-model="firstName" />
  <button @click="onClickHandler">
    button点击我
  </button>
</template><script>
  import { ref } from "vue";
  export default {
    setup() {
      const firstName = ref("女魔头");
      const onClickHandler = () => {
        firstName.value = "亚瑟"
      }
      return { firstName, onClickHandler}
    }
  }
​
</script>

这样看不清楚,就可以用@update:modelValue = "onFirstNameChanged($event)"来监听双向数据绑定中数据的变化

<template>
  <input 
   type="text"
   v-model="firstName"
   @update:modelValue="onFirstNameChanged($event)"      
         />
</template><script>
  import {ref} from "vue";
  const firstName = ref("周杰伦")
  const onFirstNameChanged = (event) => {
    console.log(event)
  }
  return { firstName, onFirstNameChanged }
</script>

1.2实现组件双向数据绑定

我会分为三个版本来进行写入,最终版是友好版本

1.2.1普通版本

App.vue

<template>
  <Test :Name="Name" @onNameChanged="onNaneChanged($event)"></Test>
</template><script>
  import {ref} from "vue";
  export default {
    components: { Test },
    name:"App",
    setup() {
      const Name = ref("EVA");
      const onNameChanged = (event) => {
        Name.value = event;
      }
      return { Name, onNameChanged }
    }
  }
</script>

Test.vue

<template>
  <div>
    {{Name}}
  </div>
  <button @click="changedName">
    点击修改App.vue里面的数据
  </button>
</template><script>
  
  export default {
    props:["Name"] //接收过来的数据
    setup(props,{emit}) {
      const changedName = () => {
        emit("onNameChanged","⚙️战机")
      }
    }
  }
​
</script>

1.2.2 升级版

App.vue

<template>
  <Test v-model="Name"></Test>
  <button @click="onClickHandler">
      我是App组件中的button
  </button>
</template><script>
  import Test from "./componetns/Test.vue"
  export default {
    components:{Test},
    name:"App",
    setup() {
      const Name = ref("EVA")
      const onClickHandler = () => {
       Name.vue = "战斗机甲"
      }
      return { firstName, onClickHandler }
    }
  }
</script>

Test.vue

<template>
  <div>
    {{modelValue}}
    <button @click="onClickHandler">
        我是Test组件中的button
    </button>
  </div>
</template><script>
  export default {
    props:["modelValue"],
    setup(props,{ emit }) {
      const onClickHandler = () => {
        emit("update:modelValue",机甲小宝)
      }
      return { onClickHandler };
    }
  }
</script>

1.2.3究极版

App.vue

<template>
  <Test v-model:firstname="firstname" v-model:lastname="lastname"></Test>
  <button @click="onClickHandler">
    我是App组件中的button
  </button>
</template><script>
import Test from "./components/Test.vue";
export default {
  components: { Test },
  name:"App",
  setup() {
    const firstName = ref("张三");
    const lastName = ref("李四");
    const onClickHandler = () => {
      firstName.value = "王五";
      lastName.value = "宝强"
    };
    return { firstName,lastName,onClickHandler }
  }
}
 
</script>

Test.vue

<template>
  <div>
    {{firstName}} {{lastName}}
    <button @click="onClickHandler">
      我是Test组件中的button
    </button>
  </div>
  
</template>
​
​
<script>
  export default {
    props:["firstName","lastName"]
    setup(props, { emit }) {
      const onClickHandler = () => {
        emit("update:firstName","刘备")
        emit("update:lastName","诸葛亮")
      };
      return { onClickHandler };
    }
  }
​
</script>

2.customRef


2.1复习防抖

防抖:监听用户的连续操作,最终只响应连续操作中的最后一次操作.

<template>
  <button @click="onClickHandler">
    button
  </button>
</template><script>
  export default {
    name:"App",
    setup() {
      const onClickHandler = debounce(() => {
        console.log("onClickHandler")
      },400)
      return { onClickHandler }
    }
  }
  
  function debounce(handler,delay) {
    let timer = null
    return function () {
      clearTimeout(timer)
      timer = setTimeout(() => {
        handler.call(this,arguments)
      },dalay)
    }
  }
</script>

2.2customRef

创建具有自定义行为的响应式数据,通过拦截响应式的读取和设置实现。

需求:创建具有防抖功能的响应式数据.监听对响应式数据的连续更改,最后只响应最后一次更改

<template>
  <input type="text" v-model="keyword" />
  {{keyword}}
</template><script>
  import { customRef } from "vue";
  export default {
    name:"App",
    setup() {
      const keyword = useDebounce("hello",400)
      return { keyword }
    }
  }
  
  function useDebounce(initialValue,delay) {
    let timer = null
    return customRef((track,trigger)) => {
      return {
        get() {
          //跟踪initialValue值的变量
          track();
          return initialValue
        },
        set(newValue) { 
          clearTimeout(timer);
          timer = setTimeout(() => {
            initialValue = newValue;
            //触发视图更新
            trigger()
          },delay)
        }
      }
    }
  }
</script>

3. setup语法🍬

npm init vue@3

<script setup></script>是一种编译时语法糖,用于在单文件组件中使用组合式API,如果你同时使用单文件组件和组合式API,建议使用该语法

它与普通语法相比,代码更加简洁,性能更加强悍,更好的TS 支持。

<script setup>
  const msg = "hello Vue3 setup";
  function log() {
    console.log(msg)
  }
</script><template>
  <div @click="log">
    {{msg}}
  </div>
</template>

[解释]  以上代码就是会被编译成为setup函数代码,也就是说此处代码会在组件每次创建实时执行,在内部声明的顶级变量和函数都可以在模版中

<script setup>
  //导入提前写好的函数,随便什么都可以处理数据
  import { capitalize } from "./helps";
  const msg = "hello vue3 setup";
</script><template>
  {{capitalize(msg)}}
</template>
<script setup>
  import { ref } from "vue";
  const count = ref(0); // count 不需要跟之前在setup里面一样返回return { count },可以直接在模版中使用
</script>
<template>
  <div @click="count++">
    {{count}}
  </div>
</template>

组件导入时不需要手动注册组件

<script setup>
  import HelloWorld from "@/components/HelloWorld"
</script>
<template>
  <HelloWorld />
</template>

如果父组件给子组件传递参数可以用defineProps接收参数并在模版上直接使用

//父组件
​
<script setup>
  import HelloWorld from "./components/HelloWorld"
</script><template>
  <HelloWorld msg="hello new setup" />
</template>
//子组件
<script setup>
  //定义该组件接收的Props
  //defineProps 在此处可以直接使用无需导入
  defineProps({msg : String})
</script>
<template> {{ msg }} </template>

如果子组件要触发父组件自定义函数请看以下例子

<script setup>
    import HelloWorld from "./components/HelloWorld"
    function onDeleteHandler() {
      alert("delete")
    }
</script>
<template>
  <HelloWorld @delete="onDeleteHandler"></HelloWorld>
</template>
<script setup>
  //defineEmits在此处可以直接使用无需导入
  defineEmits(["delete"])
</script>
<template>
    <button @click="$emit('delete')">
      delete button
    </button>
</template>

如果子组件要暴露数据可以根据以下代码来学习

<script  setup>
  const count = 0;
  //定义当前组件向外暴露的数据
  defineExpose({ count })
</script>
<script setup>
  import HelloWorld from "./components/HelloWorld";
  import { ref } from "vue";
  const instance = ref(null);
  function log() { 
    console.log(instance.value.count);
  }
</script><template>
  <HelloWorld ref="instance"></HelloWorld>
  <button @click="log">
    button
  </button>
</template>

如果在setup里面异步请求操作呢?

<script setup>
  const post = await fetch(`/api/post/1`).then((r) => r.json())
</script>