watchEffect,它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
换句话说:watchEffect相当于将watch 的依赖源和回调函数合并,当任何你有用到的响应式依赖更新时,该回调函数便会重新执行。不同于 watch,watchEffect 的回调函数会被立即执行(即 { immediate: true })
watchEffect的回调函数就是一个副作用函数,因为我们使用watchEffect就是侦听到依赖的变化后执行某些操作。
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,创造和销毁逻辑放在了一起
// 定时器注册和销毁
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 的三元运算符在 {{ }} 中展示不同的状态,具体代码如下:
<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 字段的值:
<el-table-column label="状态" min-width="100">
<template #default="{ row }">{{ row.active }}</template>
</el-table-column>在上面的代码中,我们使用了 #default 缩写语法来定义插槽,并使用对象解构来获取 row 参数。然后,我们在模板中使用 row.active 来显示 active 字段的值。
el-table-column组件没有绑定数据源:请确保你的表格组件已经正确地绑定了数据源,例如使用:data属性绑定数据源。.active字段不存在或为空值:请确保.active字段存在且有值。如果该字段不存在或为空,您的模板代码将无法正确地解析。- 样式问题:请检查您的样式是否正确,以确保表格列宽度足够容纳内容,并且字体颜色不会与背景颜色混淆。
要根据条件隐藏<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的方式隐藏起来。
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 相同的形状,还包括额外的属性 id、label 和 multiple,如果未提供,则将设置为它们的默认值。
defaultProps 是另一个对象,用于设置 children 和 label 属性的默认值。它使用与 props 相同的 label 值,除非提供了不同的值。此对象的目的是为可能未由组件的调用者指定的 props 提供回退值。
ref<T> 是一个函数,它创建对类型为 T 的值的响应式引用。常量 treeRef 被赋予一个 ElTree 类型实例的引用,该类是由 Element-Plus UI 库提供给 Vue.js 的组件之一。此引用可用于访问 ElTree 实例的属性和方法。
treeData 和 treeAllData 常量也是使用 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写法
<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, 所有的东西通过函数获取。
<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 ,在开发环境和生产环境都可以使用。
<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
- JS中使用加上
reactive 函数通常定义复杂类型的响应式数据,不能使用简单的数据类型。
<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
}
// 下面是使用的对比
//


