组件实例中的使用

setup

  1. 所以Vue3中API的入口和出口,Composition API都在写在其里面,Options API可以共存写在其中,但推荐使用全Composition API的写法
  2. setup在beforeCreate,create之前创建,因此没有this
  3. 在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用
  4. setup有两个参数,第一个是props,用于接收传递的属性对象,可以通过watchEffect监听,第二个参数是context,其包含attrs,slots,emit属性

ref

const r = ref("hello")
console.log(r)	// RefImpl {_rawValue: "hello", _shallow: false, __v_isRef: true, _value: "hello"}
console.log(r.value)	// hello
  1. ref 接受一个参数值并返回一个响应式且可改变的 ref 对象
  2. ref 对象拥有一个指向内部值的单一属性 .value
  3. 在setup内取值需要使用.value的形式
  4. setup返回的ref在模板中会自动解开,可以在模板直接使用{{r}}取值
  5. ref的本质是拷贝,与原始数据无关联性
  6. ref接受一个参数,一般是基本类型值(String 、Nmuber 、Boolean 等)或单值对象。如果传入的参数是一个对象,将会调用 reactive 方法进行深层响应转换(此时访问ref中的对象会返回Proxy对象,说明是通过reactive创建的);引用类型值(Object 、Array)使用reactive

reactive

const r2 = reactive("hello")
console.log(r2)	// value cannot be made reactive: hello

const r3 = reactive({name:"hello"})
console.log(r3)	//  Proxy {name: "hello"}
console.log(r3.name)	// hello
  1. reactive 接收一个普通对象然后返回该普通对象的响应式代理(proxy)
  2. 需要传递一个对象,否则会抛出异常
  3. setup返回出去后在模板中只能拿到其对象 // {name:“hello”}

reactive和ref都是vue3中用来创建响应式数据的api,作用等同于在vue2中的data,不同的是他们使用了ES6的PorxyAPI解决了vue2 defineProperty 无法监听数组和对象新增属性的痛点

toRef

const state = reactive({
  foo: 1,
  bar: 2,
})

const fooRef = toRef(state, 'foo')

fooRef.value++
console.log(state.foo) // 2

state.foo++
console.log(fooRef.value) // 3
const rrr = {foo: 1}

const rrr2 = ref(rrr.foo)
console.log(rrr2)	// RefImpl {_rawValue: 1, _shallow: false, __v_isRef: true, _value: 1}
console.log(rrr.foo)	// 1
console.log(rrr2.value)	// 1
rrr2.value++
console.log(rrr.foo)	// 1
console.log(rrr2.value)	// 2

const rrr3 = toRef(rrr,'foo')
console.log(rrr3)	// ObjectRefImpl {_object: {…}, _key: "foo", __v_isRef: true}
console.log(rrr.foo)	// 1
console.log(rrr3.value)	// 1
rrr3.value++
console.log(rrr.foo)	// 2
console.log(rrr3.value)	// 2
  1. toRef 可以用来为一个 reactive 对象的属性创建一个 ref
  2. 这个 ref 可以被传递并且能够保持响应性
  3. toRef的本质是引用关系,与原始数据存在关联性
  4. toRef当数据发生改变时,界面不会自动更新

toRefs-解构响应式对象数据

toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,相当于变成一个个的ref()

data

<p>{{name}}</p>	// trist
data() {
	return {
		name: "trist",
		age: 22,
		sex: "boy"
	}
}

console.log(this.age) // 22

<p>{{name}}</p>	// trist
import { reactive,toRefs } from 'vue';

setup {
	const data = reactive({
		name: "trist",
		age: 22,
		sex: "boy"
	})
	
	console.log(data.age) // 22
	
	return {
		...toRefs(data)
	}
}

如上是data中属性在vue3内的写法

  • 首先因为Vue3组合式API的写法,我们需要从vue中按需导入我们所需要的API方法
  • 我们使用reactive定义复杂数据类型的响应式数据,用一个总对象的写法,把所需的data数据写在其中
  • 在setup中,若我们需要操作data内的数据,我们通过data进行访问,如console.log(data.age)
  • 我们使用展开运算符使得定义在大对象内的数据进行解套,{{data.name}} => {{name}} 使用展开运算符便于我们取值,借助toRefs()函数可以将reactive()创建出来的响应式对象,转换为普通对象,只不过这个对象上的每个属性节点,都是ref()类型的响应式数据,使得响应式对象能进行解构并不丢失响应性

methods

methods {
	add() {
		data.age++
	}
}
setup() {
	...
	const add = () => {
		data.age++
	}
	return {
		...,
		add
	}
}
  • 定义方法函数,如在外部template中需要触发该方法,记得return出去

生命周期

在这里插入图片描述

import { onMounted } from 'vue';
setup(props, ctx) {
	...
	onMounted(() => {
		ctx.emit('loading', false);
		data.age++
		add()
	});
}	
  • 将所需的生命周期钩子导入使用就行了

watch

watch

import { ref, watch } from 'vue';
	let a = ref(1);
	watch(a,(news, olds) => {
		console.log('监听a的变化', a.value, '新值', news, '旧值', olds);
	},{ immediate: true }); //immediate:true 可以默认执行一次

watchEffect
watchEffect 监听器的升级版本,立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。

import { reactive, toRefs, ref, watch, watchEffect } from 'vue';
let aa = reactive({num:10})
setTimeout(()=> {
	aa.num++
},1000)
watchEffect(() => {
	console.log(aa.num)		// 10  // 11
});

computed

computde返回值为一个ref的实例,能在模板中自动解开

1. 使用计算属性:

import { computed } from 'vue';
 const total = computed(() => {
      let sum = 0
      data.cartList.forEach(item => {
        sum += item.goodsCount * item.sellingPrice
      })
      return sum
    })

2. 获取vuex的值:

import { mapState } from 'vuex';
computed: {
	...mapState({
		isLogin: state => state.user.isLogin
	}}			
import { reactive, toRefs, computed } from 'vue';
import { useStore } from 'vuex';
setup(props, ctx) {
	const store = useStore()
	// 直接定义在大对象中
	const data = reactive({
		isLogin: computed(() => store.state.user.isLogin)
	})
	const count = computed(() => {
      return store.state.cartCount
    })
    return {
    	...toRefs(data),
    	count
    }
}		

useStore是vuex的入口
我们可以从useStore内拿到vuex的属性和方法

在这里插入图片描述

父子组件间传值

父组件:

<template>
	<div class="home">
		<!-- 父子组件传值 -->
		<son num="66" name="trist" :age="age" @baba="getSon"><a>我是插槽</a></son>
	</div>
</template>

<script>
import son from './son.vue';
import { reactive, toRefs } from 'vue';
import { useRoute, useRouter } from 'vue-router';
export default {
	name: 'home',
	components: {
		son
	},
	setup(props, ctx) {
		// 获取当前路由信息
		const route = useRoute();
		// 全局路由的实例
		const router = useRouter();
		const state = reactive({
			name: 'trist',
			age: 22,
			sex: 'boy'
		});
		// 监听子组件事件
		const getSon = val => {
			console.log(val);
		}
		return {
			...toRefs(state),
			getSon
		};
	}
};
</script>

子组件:

<template>
	<div>
		子组件{{ son }}
		<p style="background-color: #CCCCCC;"><slot></slot></p>
		<grandson></grandson>
	</div>
</template>
<script>
import { ref } from 'vue';
import grandson from './grandson.vue';
export default {
	components: {
		grandson
	},
	// 定义要接收的值,可以设置默认值,验证规则等
	props: {
		num: {
			type: String
		},
	},
	// 如果要接受父组件里面传过来的,就要在setup里面书写参数,第一个属性,就是这个参数
	setup(props, ctx) {
		console.log(props)
		console.log(ctx.slots)
		console.log(ctx.attrs)
		const son = ref(props.num);
		// attrs用于接收除props定义以外的属性
		const attr = ctx.attrs.name
		console.log(attr)
		// 传值给父组件
		ctx.emit('baba', '我是子组件');
		return {
			son
		};
	}
};
</script>

在这里插入图片描述

v-model

回顾:vue中的数据绑定

  1. 插值(双大括号),将文本动态渲染在模板中
  2. v-bind(😃,对实例中的data进行单向的数据绑定
  3. v-model:双向数据绑定

原理:
v-model实际上是一个语法糖,它先使用v-bind对数据进行单向绑定,再监听目标对象,通过$event.target触发从而改变数据的值,实现数据的双向绑定

Vue2.x中:
v-model允许自定义prop和event,但单个组件只允许使用一个model,若如果开发者出于不同的目的需要使用其他的 prop,他们就不得不使用 v-bind.sync

// father
<son v-model="msg"></son>
// son
model: {
	prop: "get",
	event: "set"
}
props {
	get: String
}
this.$emit('set','set msg to father')

Vue3.x中:
Vue3将v-model与 .sync 进行了整合,并淘汰了 .sync 的用法,允许用户定义多个model

// father
<son v-model:name="name" v-model:age="age"></son>
// son
props: {
	name: String,
	age: Number
}
setup(props,ctx) {
	// 接受父组件的值
	console.log(props.name)
	console.log(props.age)
	// 改变父组件的值
	ctx.emit('update:name','trist')
	ctx.emit('update:age', '22')
}

框架配置中的使用

创建Vue实例

在2.X版本中创建一个vue 实例是通过 new Vue()来实现的,到了3.X中则是通过使用createApp这个 API返回一个应用实例,并且可以通过链条的方式继续调用其他的方法

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/router.js'
import store from './store'

// 创建实例
const app = createApp(App) 
app.use(router)
app.use(store)
app.mount('#app')	// 挂载

// 也可以这样写
createApp(App).use(store).use(router).mount('#app')
参数用法
config(配置)包含应用配置的对象。同Vue2中config。提供统一配置。
directive(指令)注册或检索全局指令。指令是一组具有生命周期的钩子。
mixin(混入)在整个应用范围内应用混入。一旦注册,它们就可以在当前的应用中任何组件模板内使用它。插件作者可以使用此方法将自定义行为注入组件。不建议在应用代码中使用。
mount(挂载)应用实例的根组件挂载在提供的 DOM 元素上。同Vue2中的el。
provide(搭配Inject)设置一个可以被注入到应用范围内所有组件中的值。组件应该使用 inject 来接收 provide 的值。provide 和 inject 绑定不是响应式的。
unmount(卸载)在提供的 DOM 元素上卸载应用实例的根组件。
use(使用)安装 Vue.js 插件。在同一个插件上多次调用此方法时,改插件将仅安装一次。
component(组件)注册或检索全局组件。注册还会使用给定的 name 参数自动设置组件的 name。

router

import {
	createRouter,
	createWebHistory
} from 'vue-router'

// 配置路由信息
const routes = [
	{
		path: '/test',
		name: 'Test',
		component: () => import('@/views/test.vue'),
		meta: {
			title: ""
		}
	}
]

const router = createRouter({
	history: createWebHistory(process.env.BASE_URL),
	routes,
	scrollBehavior(to, from, savedPosition) {
		return {
			x: 0,
			y: 0
		}
	}
})

export default router
  1. 新的 history 配置取代 mode,“history”: createWebHistory()
    “hash”: createWebHashHistory()
  2. 移动了 base 配置,base 配置被作为 createWebHistory (其他 history 也一样)的第一个参数传递
  3. scrollBehavior 中返回的对象与 ScrollToOptions 类似:x 改名为 left,y 改名为 top
import { useRoute, useRouter } from 'vue-router';
// 获取当前路由信息
const route = useRoute();
// 全局路由的实例
const router = useRouter();
console.log(route);
console.log(router);

在这里插入图片描述

  1. List item

封装自定义组件

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐