使用的是 组合式api
减少methds的数量
将同一个逻辑关系放到一起
使用
vue2 中使用 放到 setup(){}
在组件创建前执行
比 created 快 setup 取代 beforecreat 和 created
在 setup 中不能使用 this 指向实例
接收 props
和 context
在setup中的 const值 最后需要 return
但是数据不是 响应式的 需要通过 refs
和 reactive
和 toRefs
refs
import {refs} from 'vue'
setup(){
const msg = ref( 值') // ref返回有 value 的对象
function name() {
msg.value++
console.log(msg.value);
}
return { msg, name };
}
reactive
通过 reactive 定义引用数据类型
import {reactive} from 'vue'
setup(){
let obj = reactive ({
a:1,
b:2
})
return { obj }; // 不能解构 不然就不是响应式了
//可以通过 toRefs 就是响应式了
}
toRefs
可以响应式 也可以 解构
setup 中使用 watch // 是函数
三个参数
第一个监听的 响应式引用
第二个 回调函数
第三个可选配置项
import { reactive, watch, watchEffect } from "vue";
watch(msg,(a, b)=>{ // msg 监听的值 a 老值 b 新
console.log(a,b);
})
//watch(侦听的响应式引用,回调函数)
watchEffect(()=>{
console.log(msg.a)
})
// watchEffect(回调函数)注意不需要指定监听的属性,
//组件初始化的时候会执行一次回调函数,自动收集依赖
// 依赖没变 就不会触发 可以监听 对象属性
区别
watchEffect
不用指定监听属性 只要 回调中引用了响应式的数据, 只要依赖的属性改变 就会 执行
watch
监听特定属性
setup 中使用 computed// 是函数
先引入
setup(){
const uesr = reactive({
name: '123',
reverseMsg: computed(()=>{
return msg.value.split('')
})
})
log(user.reverseMsg)
}
setup(props , context){} 参数
props : 响应式的 夫传子的
因为没有this 所以需要用 props 先用
props 接收数据 才能用
context 对象 暴露setup中有用的值
context.attrs
=> 非响应式对象 等同于$attrs 可以拿到组件的信息 例如 class id
context.slot
=> 插槽
context.emit
=> 自定义事件
context.expose
=> 自定义事件
context.attrs
父:
<Zhujian class="class" />
子
console.log(context.attrs)
context.emit
父
<Zhujian class="class" @事件名='事件名'/>
methods:{
事件名(value){
log(value) // value 就是传递的值
}
}
子
setup(){
function sendParent (){
context.emit('事件名','传递的值')
}
return {sendParent }
}
context.expose
使用渲染函数
当子组件是 返回的 渲染函数的话
例如
setup(){
return ()=> h('div', 20)
}
那么就替换掉 本来组件的所有内容 变成 20
想要拿到 渲染函数中的数据
父
<Zhujian class="class" ref="content"/>
mounted(){
log(this.$refs.content) // 就能获取到 子中暴露的方法 和 值
}
子
setup(){
let aaa = ref(20)
context.expose({
aaa // 需要暴露的方法 和 值 代替原先的return
})
}
Provide 和 Inject 跨级通讯
父
import {provide}
setup(){
const name = ref('123')
provide('传递的名' , 传递的值 ) //如果是ref 就不要.value 不然还是非响应式的
}
子
import {inject} from '
setup(){
inject('传递的值')
}
插槽
v-solt 简写 ‘#’ 作用域插槽 简写 #default
子插槽
<solt></solt> // 占位
父
<content> <div>123</div> </content>
那么页面就会展示 123 将组件内的html 替换掉 solt 标签
具名插槽
需要多个插槽 就取个名
子
<solt name="aaa"></solt>
父
<Content>
// v-solt 只能写在 template里
<template v-solt:aaa>
<div>123 {{msg}} </div>
// msg 可以用 只能拿到 父的 msg
// 子组件不能访问
</template>
</Content>
给solt 写默认值
直接在 子中的solt 写就能替换 没有提供内容就会渲染 如果没有写逻辑也会默认展示
<solt> <div>默认</div> </solt>
想拿到 子组件的数据
作用 父组件 通过插槽替换内容 但是数据通过子组件来获取
作用域插槽
子
<solt :list="list"> </solt>
data(){
return{ list: [1,2,3,4]}
}
父
<Content>
<template v-solt:default="值">
{{值}}
</template>
</Content>
proxy 解决 跨域
在 vue.config.js 中设置
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
host: '0.0.0.0',
open: true,
proxy: {
'/path': {
// target:'https://i.maoyan.com',
target:'https://e-learning.oumeng.com.cn',
changeOrigin: true,
ws: true,
pathRewrite: {
'^/path': '/'
}
}
}
}
})
在请求的地方 取消前缀 改成 path
vuex
state
拿取数据 this.$store.state
mapstate
辅助函数
作用 直接用数据 不用this.$store
先引用
computed :{ ...mapstate([ 需要使用的键 ]) }
mutactions 同步操作
mutations:{
方法名(state, vaule){
state.value ++
}
}
使用 this.$store.commit( ' store 中的方法名 ' ,' 需要传递的参数 ')
actations 异步操作
actations(context){
// context 与store 中实例一样的方法和属性
修改 state 中的数据 通过 ` context.commit() `
}
在组件中 触发
mounted(){
this.$store.dispath('方法名')
}
vuex 中的逻辑
actions:{
方法名(){
log()
}
}
getters 计算属性
getters : { // 只要依赖值不变就不会变
revermsg(state){
return state.msg.split('').reverse().join('')
},
revermsgLength(state, getters){
// getters表示当前store 中的getters对象
可以通过 getters.revermsg 获取到
}
}
使用 this.$store.revermsg
自定义指令
局部注册
<input v-focus/>
directives:{ // 自定义指令
focus:{
inserted(el, binding){ // 被绑定的元素插入父节点的时候调用
// el 表示指令绑定个元素
// binding 对象 name 指令名 value 绑定值
el.focus()
}
}
}
全局注册
Vue.directive('指令名' , 方法对象)
Vue.directive('focus', {
inserted(el){
el.focus()
}
})
$nextTick
作用 当dom 渲染之后 自动 调用 类似于 settimeout(){}
使用 在方法中
this.$nextTick(()=>{
逻辑
})