前端系列15集-watch,watchEffect,eventBus

2023-10-08 19:10:11 浏览数 (2)

watchEffect,它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

换句话说:watchEffect相当于将watch 的依赖源和回调函数合并,当任何你有用到的响应式依赖更新时,该回调函数便会重新执行。不同于 watchwatchEffect 的回调函数会被立即执行(即 { immediate: true }

watchEffect的回调函数就是一个副作用函数,因为我们使用watchEffect就是侦听到依赖的变化后执行某些操作。

代码语言:javascript复制
import { watchEffect, ref } from 'vue'

const count = ref(0)
watchEffect((onInvalidate) => {
  console.log(count.value)
  onInvalidate(() => {
    console.log('执行了onInvalidate')
  })
})

setTimeout(()=> {
  count.value  
}, 1000)

定义一个定时器,或者监听某个事件,我们需要在mounted生命周期钩子函数内定义或者注册,然后组件销毁之前在beforeUnmount钩子函数里清除定时器或取消监听。这样做我们的逻辑被分散在两个生命周期,不利于维护和阅读。

如果我利用watchEffect,创造和销毁逻辑放在了一起

代码语言:javascript复制
// 定时器注册和销毁
watchEffect((onInvalidate) => {
  const timer = setInterval(()=> {
    // ...
  }, 1000)
  onInvalidate(() => clearInterval(timer))
})

const handleClick = () => {
 // ...
}
// dom的监听和取消监听
onMounted(()=>{
  watchEffect((onInvalidate) => {
    document.querySelector('.btn').addEventListener('click', handleClick, false)
    onInvalidate(() => document.querySelector('.btn').removeEventListener('click', handleClick))
  })
})

利用watchEffect做一个防抖节流

代码语言:javascript复制
const id = ref(13)
watchEffect(onInvalidate => {
   // 异步请求
  const token = performAsyncOperation(id.value)
  // 如果id频繁改变,会触发失效函数,取消之前的接口请求
  onInvalidate(() => {
    // id has changed or watcher is stopped.
    // invalidate previously pending async operation
    token.cancel()
  })
})

可以使用 Vue.js 的三元运算符在 {{ }} 中展示不同的状态,具体代码如下:

代码语言:javascript复制
<el-table-column label="状态" min-width="100">
  {{row.status === 1 ? '已完成' : row.status === 2 ? '进行中' : '未开始'}}
</el-table-column>

在上面的代码中,我们使用了两个嵌套的三元运算符来实现根据 row.status 的值显示不同的状态。如果 row.status 的值为 1,则显示 "已完成",如果值为 2,则显示 "进行中",否则显示 "未开始"

在 Vue 3 中,可以使用 v-slot 的缩写语法(#)来指定插槽的位置。对于 el-table-column 组件中的插槽,您可以将模板语法放置在 <template v-slot:default><template #default> 标签内。

下面是根据您提供的代码示例修改后的 Vue 3 代码,用于在 el-table-column 组件中显示 sysUser.active 字段的值:

代码语言:javascript复制
<el-table-column label="状态" min-width="100">
  <template #default="{ row }">{{ row.active }}</template>
</el-table-column>

在上面的代码中,我们使用了 #default 缩写语法来定义插槽,并使用对象解构来获取 row 参数。然后,我们在模板中使用 row.active 来显示 active 字段的值。

  1. el-table-column 组件没有绑定数据源:请确保你的表格组件已经正确地绑定了数据源,例如使用 :data 属性绑定数据源。
  2. .active 字段不存在或为空值:请确保 .active 字段存在且有值。如果该字段不存在或为空,您的模板代码将无法正确地解析。
  3. 样式问题:请检查您的样式是否正确,以确保表格列宽度足够容纳内容,并且字体颜色不会与背景颜色混淆。

要根据条件隐藏<el-form-item>,可以使用Vue的条件渲染指令v-if或v-show。

使用v-if指令时,只有当条件为真时,元素才会被渲染到页面上。如果条件变为假,则该元素从DOM中删除。

例如, 如果您想要在表单项不为空时才显示密码字段,您可以将v-if指令添加到包装表单项的

元素中:

代码语言:javascript复制
<div v-if="formData.name !== ''">
  <el-form-item label="密码" prop="name">
    <el-input
      class="ls-input"
      v-model="formData.passwd"
      placeholder="请输入密码"
      clearable
    />
  </el-form-item>
</div>

在这个例子中,<el-form-item>只有在formData.name不为空时才会被渲染出来。

另一种选择是使用v-show指令。与v-if不同的是,当条件为假时,元素仍然存在于DOM中,只是样式设置为display:none。

例如,如果您希望在表单项不为空时显示密码字段,您可以将v-show指令添加到元素中:

代码语言:javascript复制
<el-form-item label="密码" prop="name" v-show="formData.name !== ''">
  <el-input
    class="ls-input"
    v-model="formData.passwd"
    placeholder="请输入密码"
    clearable
  />
</el-form-item>

在这个例子中,当formData.name不为空时,<el-form-item>将显示出来,否则它将以display:none的方式隐藏起来。

代码语言:javascript复制
data | 展示数据 |

empty-text | 内容为空的时候展示的文本 |
    
node-key | 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的 |

render-after-expand | 是否在第一次展开某个树节点后才渲染其子节点 |

load 加载子树数据的方法,仅当lazy属性为true时生效

render-content 树节点的内容区的渲染Function

highlight-current 是否高亮当前选中节点,默认值是false

default-expand-all 是否默认展开所有节点

expand-on-click-node
是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。

这段代码使用了 Vue 3 Composition API 中的 defineProps 函数来定义一个名为 props 的响应式属性对象,并通过 withDefaults 函数设置了默认值。

首先,defineProps 函数是用于定义组件接收的 props 属性的函数。<TreeFilterProps> 泛型表示这个组件接收的 props 类型,即传递给组件的数据类型。这个函数返回一个 props 对象,其中每个属性都对应着组件中接收的 prop 属性。在这个例子中,这个 props 对象是空的,也就是说这个组件没有接收任何 props 属性。

接下来,withDefaults 函数是一个辅助函数,用于设置默认值。此函数接收两个参数:第一个是需要设置默认值的对象,第二个是一个包含默认值的对象。在这个例子中,我们将 defineProps<TreeFilterProps>() 返回的空对象作为第一个参数传入,表示我们需要给这个对象设置默认值;然后,我们将一个包含默认值的对象作为第二个参数传入,其中 id: 'id' 表示默认的 id 属性是 'id'label: 'label' 表示默认的 label 属性是 'label'multiple: false 表示默认的 multiple 属性是 false

因此,这段代码的作用是定义一个响应式的 props 属性对象,并为其设置默认值。如果在父组件中没有传递对应的 props 属性,则会使用默认值。

defineProps<TreeFilterProps>() 是一个函数调用,它将 props 对象的预期类型定义为 TreeFilterProps。它返回一个所有属性均设置为 undefined 的对象。

withDefaults() 是一个函数,它接受两个参数:一个具有可选属性的对象(在这种情况下是 props),以及一个具有默认值的对象(在这种情况下是 { id: 'id', label: 'label', multiple: false })。它将这两个对象合并在一起,如果有任何冲突,则优先使用默认值。

生成的 props 对象将具有与 TreeFilterProps 相同的形状,还包括额外的属性 idlabelmultiple,如果未提供,则将设置为它们的默认值。

defaultProps 是另一个对象,用于设置 childrenlabel 属性的默认值。它使用与 props 相同的 label 值,除非提供了不同的值。此对象的目的是为可能未由组件的调用者指定的 props 提供回退值。

ref<T> 是一个函数,它创建对类型为 T 的值的响应式引用。常量 treeRef 被赋予一个 ElTree 类型实例的引用,该类是由 Element-Plus UI 库提供给 Vue.js 的组件之一。此引用可用于访问 ElTree 实例的属性和方法。

treeDatatreeAllData 常量也是使用 ref 创建的。它们都被赋予了一个对象数组的空数组,其中包含键值对,其中键的类型为 string,值的类型为 any。这些引用可用于存储将由 ElTree 组件动态呈现的数据。

setSelected 函数中,首先检查了 props.multiple 参数是否为 true,如果是的话则判断 props.defaultValue 是否为数组,如果是则将其赋值给 selected.value 变量,否则将其包装成一个数组并赋值给 selected.value 变量。

接着,如果 props.multiple 参数不为 true,则判断 props.defaultValue 是否为字符串类型,如果是的话直接将其赋值给 selected.value 变量,否则将 selected.value 变量赋值为空字符串。

后端项目打包部署

在控制台中执行mvn clean package命令把项目打成一个jar包,在控制台日志中看到如下信息表明打包成功

使用XShell6 ssh客户端连接软件登录自己的Linux云服务器,执行cd /usr/local命令进入/usr/local目录

执行mkdir logs命令创建日志文件夹

给项目启动和关闭bash脚本文件授予读、写和执行权限

chmod 775 startup.sh stop.sh

执行vim ./conf/nginx.conf 命令修改nginx.conf配置文件

$ npm install --save vue3-eventbus

代码语言:javascript复制
import eventBus from 'vue3-eventbus'
app.use(eventBus)
代码语言:javascript复制
// Button.vue
import bus from 'vue3-eventbus'
export default {
    setup() {
        bus.emit('foo', { a: 'b' })
    }
}

mitt

代码语言:javascript复制
export default class EventBus {
    constructor() {
     this.event = {}
    }
}
组合式API介绍

Vue3提供两种组织代码逻辑的写法:

  • 通过data、methods、watch 等配置选项组织代码逻辑是选项式(Options) API写法
代码语言:javascript复制
<template>
  <p>计数器:{{ count }}</p>
  <button @click="increment">累加</button>
</template>

<script>
import { ref } fro 'vue'
export default {
  setup () {
    // 打印undefined
    console.log(this)
    // 定义数据和函数
    const count = ref(0)
    const increment = () => {
      count.value  
    }
    // 返回给模板使用
    return { count , increment}
  }
}
</script>
  • setup中通过Vue提供的内置函数组合,实现代码功能,就是Composition API写法。
  • Composition API有什么好处?可复用,可维护。
  • setup 函数是 Vue3 特有的选项,作为组Composition API的起点。
  • 函数中 this 不是组件实例,是 undefined
  • 如果数据或者函数在模板中使用,需要在 setup 返回。
  • 在Vue3的Composition API项目中几乎用不到 this , 所有的东西通过函数获取。
代码语言:javascript复制
<template>
  <p>计数器:{{ count }}</p>
  <button @click="increment">累加</button>
</template>

<script setup>
import { ref } from 'vue'
// 定义数据和函数
const count = ref(0)
const increment = () => {
  count.value  
}
</script>
  • 在 script setup 中声明的变量都可以在模板使用,数据,函数,组件。
  • 不需要export default。
  • 不需要return。

Vue3 的 setup 中无法使用 this 这个上下文对象,但是如果我想使用 this 上的属性和方法应该怎么办呢。虽然不推荐这样使用,但依然可以通过 getCurrentInstance 方法获取上下文对象:

注意

ctx 只能在开发环境使用,生成环境为 undefined 。 推荐使用 proxy ,在开发环境和生产环境都可以使用。

代码语言:javascript复制
<script setup>
import { getCurrentInstance } from 'vue'
// 以下两种方法都可以获取到上下文对象
const { ctx } = getCurrentInstance()
const { proxy }  = getCurrentInstance()
</script>
代码语言:javascript复制
<template>
  <p>计数器:{{ count }}</p>
  <button @click="increment">累加</button>
</template>

<script setup>
import { ref } from 'vue'
// 创建响应式数据对象
const count = ref(0)
const increment = () => {
  // 在JS中使用的时候需.value
  count.value  
}
</script>
  • ref 可以把简单数据或者复杂数据转换成响应式数据,
  • 注意
    • JS中使用加上 .value
    • template模板中使用省略.value

reactive 函数通常定义复杂类型的响应式数据,不能使用简单的数据类型。

代码语言:javascript复制
<template>
  <div>
    <p>姓名:{{state.name}}</p>
    <p>年龄:{{state.age}}</p>
    <button @click="addAgeHandle"> 1</button>
  </div>
</template>

<script>
import { reactive } from "vue"; 
// 创建响应式数据对象
const state = reactive({ name: 'xxx', age: 25 })
const addAgeHandle = () => {
  state.age  
}
</script>
<template>
  <div>
    <p>姓名:{{state.name}}</p>
    <p>年龄:{{state.age}}</p>
    <button @click="addAgeHandle1"> 1</button>
    <button @click="addAgeHandle2"> 1</button>
  </div>
</template>

<script>
import { reactive, ref } from "vue"; 
// 创建响应式数据对象
let user1 = reactive({ name: 'xxx', age: 25 })
let user2 = ref({ name: 'xxx', age: 25 })
const addAgeHandle = () => {
  state.age  
}

// 下面是使用的对比
// 


	

0 人点赞