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
}
// 下面是使用的对比
//