当前位置: 首页 > article >正文

【VUE3】VUE组合式(响应式)API常见语法

pnpm常用命令

pnpm i //pnpm安装

VUE3常见语法汇总

ref()  //const count = ref(0)  //count.value(访问值,包括对象要加.value) //任何类型的值,包括深层嵌套的对象或则JS内置数据结构 
await nextTick() //要等待 DOM 更新完成后再执行额外的代码,可以使用 nextTick() 全局 API
reactive() //只能用于对象类型 (对象、数组和如 Map、Set 这样的集合类型)它不能持有如 string、number 或 boolean 这样的原始类型
模板语法1:<span>Message: {{ msg }}</span>
模板语法2(插入HTML):<span v-html="rawHtml"></span> 
指令:<div v-bind:id="xd"></div> //常见指令 :id、:disable、:href
计算属性:(1)、import { ref, computed } from "vue";  (2)、const booksLength = computed(() => {  return list.value.books.length > 0 ? "Yes" : "No"; }); (3)、 <span>{{ booksLength }}</span> // 不是以一个函数执行,不加()

条件渲染:v-if、v-else、v-else-if、v-show
列表渲染:(1)、v-for(<li v-for="item in courseList">{{ item }}</li>) ;(2)、of(<li v-for="item of courseList">{{ item }}</li>#v-if和v-for是不推荐一起使用在同一个标签
事件监听:v-on:click="handler"  或则 @click="handler"
侦听器:watch(我们需要在状态变化时执行一些“副作用:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态)
侦听器:watchEffect()
onMounted:是一个生命周期钩子(生命周期函数),用于在组件实例被挂载到 DOM 上后执行代码。
onUnMounted://组件卸载之后


  • 计算属性
    为什么后面不加(),不是以一个函数执行
    使用缓存,减少性能消耗
<script setup>
import { ref, computed } from "vue";
const list = ref({
  books: [
    "语文",
    "数学",
    "英语",
  ],
});

// 一个计算属性 ref
const booksLength = computed(() => {
  return list.value.books.length > 0 ? "Yes" : "No";
});
</script>

<template>
  <p>拥有书籍的个数:</p>
  <span>{{ booksLength }}</span>
</template>
  • 可写计算属性
<script setup>
import { ref, computed } from "vue";
const firstName = ref("老");
const lastName = ref("王");

const fullName = computed({
  // getter
  get() {
    return firstName.value + " " + lastName.value;
  },
  // setter
  set(newValue) {
    // 注意:我们这里使用的是解构赋值语法
    [firstName.value, lastName.value] = newValue.split(" ");
  },
});
// fullName.value = "范 冰冰";
</script>

<template>
  <p>Has published books:</p>
  <span>{{ fullName }}</span>
</template>
  • 列表渲染

v-if和v-for是不推荐一起使用在同一个标签

当它们同时存在于一个节点上时,v-if 比 v-for 的优先级更高

这意味着 v-if 的条件将无法访问到 v-for 作用域内定义的变量别名

对象的循环便利:便利对象的值、键、索引如下:

<script setup>
import { ref } from "vue";
const courseObject = ref({ front: "js", back: "java" });
</script>

<template>
  <ul>
    <li v-for="(value, key, index) in courseObject" v-if="!value">
      {{ value }} - {{ key }} -{{ index }}
    </li>
  </ul>
</template>
  • 事件修饰符
.stop  //阻止事件的向上传播,阻止上层事件的发生
.prevent //阻止行为
.self //提交事件将不再重新加载页面
.capture //添加事件监听器时,使用 `capture` 捕获模式
.once //点击事件最多被触发一次
.passive //滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成
  • 按键修饰符
.enter //enter键
.tab 
.delete (捕获“Delete”和“Backspace”两个按键)
.esc
.space
.up
.down
.left
.right
  • 系统按键修饰符
.ctrl
.alt
.shift
.meta
  • 表单输入绑定

(1)、没使用vue时需要手动处理双向数据绑定

<input
  :value="text"
  @input="event => text = event.target.value"
>

(2)、v-model 指令帮我们简化了这一步骤

<input v-model="text">
  • 侦听器
    我们需要在状态变化时执行一些“副作用:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态
<script setup>
import { ref, watch } from "vue";

const question = ref("");
const answer = ref("答案");
const loading = ref(false);

// 可以直接侦听一个 ref
watch(question, (newQuestion) => {
  if (newQuestion.includes("?")) {
    loading.value = true;
    answer.value = "Thinking...";
    setTimeout(() => {
      answer.value = "是的";
    }, 1000);
  }
});
</script>

<template>
  <p>
    提问问题
    <input v-model="question" :disabled="loading" />
  </p>
  <p>{{ answer }}</p>
</template>

(1)即时回调侦听器

watch 默认是懒执行的:仅当数据源变化时,才会执行回调

watch(
  source,
  (newValue, oldValue) => {
    // 立即执行,且当 `source` 改变时再次执行
  },
  { immediate: true }
)

(2)、一次性侦听器

源变化时触发一次 once: true

watch(
  source,
  (newValue, oldValue) => {
    // 当 `source` 变化时,仅触发一次
  },
  { once: true }
)

watch vs. watchEffect​

wathchEffect(() => {
	console.log('count is :${obj.value.count}');
})
 watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:
  • watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。

  • watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。

  • 组件上的ref

使用场景

1. 获取某个元素的位置、宽高
2. 子组件的内容
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'

const child = ref(null)

onMounted(() => {
  // child.value 是 <Child /> 组件的实例
})
</script>

<template>
  <Child ref="child" />
</template>
  • Vue3的所有生命周期函数流程

在这里插入图片描述

  • Vue3生命周期函数整理总结

初始化阶段

- beforeCreate
- created

此阶段无法获取template里面DOM节点

<script setup>
/**
  组件加载前
/
</script>

挂载阶段

- onMounted(挂载之后)
- onBeforeMount

更新阶段

- onBeforeUpdate
- onUpdated

卸载阶段

- onBeforeUnmount
- onUnmounted(卸载之后)
第7集 Vue3单页面组件开发基础—组件定义+使用

组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构

在这里插入图片描述

  • 定义组件
<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>
  • 使用组件

要使用一个子组件,我们需要在父组件中导入它

<script setup>
import ButtonCounter from './ButtonCounter.vue'
</script>

<template>
  <h1>Here is a child component!</h1>
  <ButtonCounter />
</template>
  • 父子组件参数传递

    defineProps 是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入。

(1)、子组件定义

<script setup>
defineProps(['title'])
</script>

<template>
  <h4>{{ title }}</h4>
</template>

(2)、Demo代码2

const props = defineProps({
  width: {
    type: String,
    default: "25%",
    required: false,
  },
  title: {
    type: String,
    default: "",
    required: false,
  },
  dialogVisible: {
    type: Boolean,
    default: false,
    required: true,
  },
});
  • 父组件传递函数给子组件
// 子组件
defineEmits(["childClick"]);
@click="$emit('childClick')"

// 父组件
@childClick="()=>{}"
第9集 Vue3单页面组件开发基础—插槽
  • defineExpose
// 子组件
const xd=ref(0)
defineExpose({xd})

// 父组件
const childRef=ref('')
<child-component ref='childRef' />
<span>{{childRef.xd}}<span/>
  • 插槽 slot
// 子组件
<template>
  <slot></slot>
</template>

// 父组件
<child-component>
  小滴课堂
</<child-component>

第五章 深入掌握Vue3组件进阶内容

第1集 Vue3单页面组件开发进阶—组件注册+命名
  • 全局注册
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import ChildComponent from "./ChildComponent.vue";

const app = createApp(App);
app.component("ChildComponent", ChildComponent);
app.mount("#app");

全局注册虽然很方便,但有以下几个问题:

  1. 不必要的文件体积
    全局注册,但并没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”),如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。

  2. 难维护
    全局注册在大型项目中使项目的依赖关系变得不那么明确,在父组件中使用子组件时,不太容易定位子组件的实现,和使用过多的全局变量一样,这可能会影响应用长期的可维护性

第2集 Vue3单页面组件开发进阶—props
  • props声明
<script setup>
const props = defineProps(['xd'])

console.log(props.xd)
</script>
<script setup>
defineProps({
  xd: String,
  name: String
})
</script>

defineProps中定义属性是单向数据流、如果需要更改可以再维护一个变量

const props = defineProps(['xd'])

// 计数器只是将 props.xd 作为初始值
// 像下面这样做就使 prop 和后续更新无关了
const counter = ref(props.xd)

进一步处理/转换

const props = defineProps(['xd'])

// 该 prop 变更时计算属性也会自动更新
const newXd = computed(() => props.xd+'老王')
第3集 Vue3单页面组件开发进阶—defineModel
  • 双向数据绑定
// 子组件
<script setup>
const model = defineModel();
</script>

<template>
  <h2>子组件</h2>
  <input v-model="model" />
</template>
// 父组件
<script setup>
import ChildComponent from "./ChildComponent.vue";
import { ref } from "vue";

const xd = ref("小滴课堂");
</script>

<template>
  <h1>父组件</h1>
  <span>{{ xd }}</span>
  <ChildComponent v-model="xd"></ChildComponent>
</template>
  • 多数据绑定
// 父组件
<ChildComponent v-model:xd="xd" v-model:aa="aa"></ChildComponent>

// 子组件
const xd = defineModel("xd");
const aa = defineModel("aa");

<input type="text" v-model="xd" />
<input type="text" v-model="aa" />
第4集 Vue3单页面组件开发进阶—依赖注入
  • provide + inject
    在这里插入图片描述
import { createApp } from 'vue'

const app = createApp({})

app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
<script setup>
import { inject } from 'vue'

const message = inject('message')
</script>
  • 和响应式数据配合
<!-- 在供给方组件内 -->
<script setup>
import { provide, ref } from 'vue'

const xd = ref('小滴课堂')

function updateXd() {
  xd.value = 'xdclass.net'
}

provide('xd', {
  xd,
  updateXd
})
</script>
<!-- 在注入方组件 -->
<script setup>
import { inject } from 'vue'

const { xd, updateXd } = inject('xd')
</script>

<template>
  <button @click="updateXd">{{ xd }}</button>
</template>
第5集 Vue3单页面组件开发进阶—KeepAlive

概念:KeepAlive 是一个内置组件,它的功能是在多个组件间动态切换时,缓存被移除的组件实例。

<script setup>
import ChildComponent1 from "./ChildComponent1.vue";
import ChildComponent2 from "./ChildComponent2.vue";
import { ref } from "vue";
const xd = ref(true);
</script>
<template>
  <h1>父组件</h1>
  <button @click="() => (xd = !xd)">切换组件</button>
  <KeepAlive><ChildComponent1 v-if="xd" /></KeepAlive>
  <ChildComponent2 v-if="!xd" />
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
</script>

<template>
  <h2>子组件1</h2>
  <span>count:{{ count }}</span
  ><button @click="count++">+</button>
</template>

第六章 实现单页面应用Vue3规模化的路由使用—Vue Router

第1集 Vue3单页面实现规模化Vue Router基础—入门使用
  • 安装
pnpm install vue-router@4 //@4:指定版本
  • 使用
import { createRouter, createWebHashHistory } from "vue-router";

import ChildComponent1 from "./ChildComponent1.vue";
import ChildComponent2 from "./ChildComponent2.vue";
const routes = [
  { path: "/one", component: ChildComponent1 },
  { path: "/two", component: ChildComponent2 },
];
const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

export default router;
<script setup>
import { ref } from "vue";

const xd = ref(true);
</script>
<template>
  <h1>父组件</h1>
  <p>
    <!-- 通过传递 `to` 来指定链接 -->
    <router-link to="/one">去组件1</router-link> <br />
    <router-link to="/two">去组件2</router-link>
  </p>
  <div>
    <!-- 路由出口 -->
    <router-view></router-view>
  </div>
</template>
第2集 Vue3单页面实现规模化Vue Router基础—嵌套路由+编程式导航
  • 嵌套路由
import { createRouter, createWebHashHistory } from "vue-router";
import ChildComponent1 from "./ChildComponent1.vue";
import ChildComponent2 from "./ChildComponent2.vue";
import ChildComponent3 from "./ChildComponent3.vue";

const routes = [
  {
    path: "/one",
    component: ChildComponent1,
  },
  {
    path: "/two",
    component: ChildComponent2,
    children: [
      {
        path: "aa",
        component: ChildComponent3,
      },
    ],
  },
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

export default router;
  • 编程式导航
<script setup>
import router from "./router.js";
const routerChange = (n) => {
  router.push(n);
};
</script>
<template>
  <h1>父组件</h1>
  <p>
    <button @click="routerChange('/one')">打开组件1</button> <br />
    <button @click="routerChange('/two')">打开组件2</button><br />
    <button @click="routerChange('/two/aa')">打开组件3</button>
  </p>
  <div>
    <router-view></router-view>
  </div>
</template>
第3集 Vue3单页面实现规模化Vue Router基础—命名+重定向
  • 命名+重定向
    重定向:redirect
//router.js
import { createRouter, createWebHashHistory } from "vue-router";
import ChildComponent1 from "./ChildComponent1.vue";
import ChildComponent2 from "./ChildComponent2.vue";
import ChildComponent3 from "./ChildComponent3.vue";

const routes = [
  {
    path: "/",
    redirect: "/one",
  },
  {
    path: "/one",
    name: "one",
    component: ChildComponent1,
  },
  {
    path: "/two",
    name: "two",
    component: ChildComponent2,
    children: [
      {
        path: "three",
        name: "three",
        component: ChildComponent3,
      },
    ],
  },
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

export default router;
<script setup>
import router from "./router.js"
const routerChange = (n) => {\
	router.push({ name: n });
}
</script>
<template>
<button @click="routerChange(three)">打开组件3</button>
</template>
第4集 Vue3单页面实现规模化Vue Router基础—路由传参
  • 传参

query(推荐方式)

//父组件
//Url传参
<router-link :to="/one?xd=小滴课堂&state=xdclass">打开组件2</router-link>

//对象传参
<router-link
  :to="{ path: '/one', query: { xd: '小滴课堂', state: 'xdclass' } }"
  >打开组件1</router-link
>
//子组件
import { useRoute } from 'vue-router'
const route = useRoute();
<span>{{route.query.xd }}</span>
<span>{{route.query.state}}</span>
  • params
//父组件中通过名字的方式传参
<router-link :to="{ name: 'one', params: { xd: '小滴课堂' } }"
  >打开组件1</router-link
>

//router.js 配置params方式传参
path: "/one/:xd"

//子组件获取参数
route.params.xd 

-变程式导航传参

const routerChange = (n, obj) => {
  router.push({ path: n, query: obj });
};
第5集 Vue3单页面实现规模化Vue Router进阶—历史记录模式+导航守卫
  • 不同的历史记录模式
  1. 哈希模式:createWebHashHistory() 推荐
  2. html5模式:createWebHistory()
  • 导航守卫(可以做权限验证)
//router.js
router.beforeEach((to, from, next) => {
  if (to.meta.isAuth) {
    if (localStorage.getItem("token") === "1") {
      next();
    } else {
      alert("请先登录");
    }
  } else {
    next();
  }
});
第6集 Vue3单页面实现规模化Vue Router进阶—路由懒加载
  • 路由懒加载
component: () => import("./ChildComponent1.vue"),

在这里插入图片描述

第七章 玩转Vue3拥有组合式API的状态管理库—Pinia

第1集 为什么使用Pinia?
  • 为什么使用Pinia?
  1. Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态
  2. 如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state = reactive({}) 来共享一个全局状态
  3. Devtools 支持
  4. 热更新
  5. 支持服务端渲染
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }

  return { count, increment }
})
  • 对比Vuex
  1. 提供了一个更简单的 API,符合组合式 API 风格的 API
  2. 搭配 TypeScript 一起使用时有非常可靠的类型推断支持
第2集 Vue3跨组件共享状态Pinia—安装+使用示例
  • 安装
pnpm i pinia@2
  • 使用

(1)、引入pinia

// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

(2)、定义 defineStore
写法1(推荐方式):

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }

  return { count, increment }
})

写法2:

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => {
    return { count: 0 }
  },
  // 也可以这样定义
  // state: () => ({ count: 0 })
  actions: {
    increment() {
      this.count++
    },
  },
})

(2)、使用

import {useCounterStore } from "./store/counter"
const counter=useCounterStore ();

pinia数据:<span>{{ counter.count }}</span>
<button @click="counter.increment"></botton>

http://www.kler.cn/a/412036.html

相关文章:

  • leetcode hot100【LeetCode 215.数组中的第K个最大元素】java实现
  • 深入了解决策树---机器学习中的经典算法
  • 一个高度可扩展的 Golang ORM 库【GORM】
  • 使用ENSP实现默认路由
  • Pytorch微调深度学习模型
  • ctfshow单身杯2024wp
  • 光耦——光伏储能的隐形动力,引领绿色能源迈向新纪元
  • 论文阅读:A Software Platform for Manipulating theCamera Imaging Pipeline
  • unity | 动画模块之卡片堆叠切换
  • 34 基于单片机的指纹打卡系统
  • 林业产品推荐系统:Spring Boot技术内幕
  • java实现归并排序和快速排序
  • Linux操作系统2-进程控制3(进程替换,exec相关函数和系统调用)
  • 【Linux】/proc/sys/vm/drop_caches
  • 使用 Nginx 在 Ubuntu 22.04 上安装 LibreNMS 开源网络监控系统
  • i春秋-文件包含绕过(PHP伪协议的使用)
  • Altium Designer学习笔记 22-23 PCB快捷键设置_PCB模块化布局
  • JDBC 设置 PostgreSQL 查询中 any(?) 的参数
  • Vue 的 computed 如何实现接受一个参数
  • 【模型学习之路】PyG的使用+基于点的任务
  • Mybatis---MyBatis映射文件SQL深入、多表查询
  • Amazon AWS公司介绍
  • docker部署的服务器数据备份
  • 16.迭代器模式设计思想
  • Python学习指南 + 谷歌浏览器如何安装插件
  • 【通俗理解】神经网络中步长缩小的奥秘:优化算法与卷积操作的影响