前言
不知不觉已经记录了这么多的知识点,更新一下吧。
可能比较杂乱,请谅解。
正文
ref()
和reactive()
函数都是定义响应式数据的函数,ref
更倾向于定义简单类型和数组,reactive
定义对象- es6语法解构
reactive
所定义的响应式对象,会让其失去响应式。应用...toRefs
方法 - 基本写法
<script lang="ts">
import {defineComponent, ref} from 'vue';
export default defineComponent({
name: 'App',
setup() {
const girls = ref(['貂蝉', '昭君', '大乔', '小乔'])
const selectedGirl = ref('')
const selectGirl = (index: number): void => {
selectedGirl.value = girls.value[index]
}
//返回才能在模板中使用
return {
girls,
selectedGirl,
selectGirl
}
}
});
</script>
- 改进上述代码
<script lang="ts">
import {reactive, toRefs} from 'vue';
interface DataProps {
girls: string[],
selectedGirl: string,
selectGirl: (index: number) => void;
}
export default {
name: 'App',
setup() {
const data: DataProps = reactive({
girls: ['貂蝉', '昭君', '大乔', '小乔'],
selectedGirl: '',
selectGirl(index: number): void {
data.selectedGirl = data.girls[index]
},
name: 'zed'
})
return {...toRefs(data)}
}
};
</script>
- 接口中的数据,只要被检测数据全部拥有且类型正确,即可
- 生命周期函数
- 3.x的生命周期函数需要引入,2.x原有的不需要
- 3.x都在
setup()
中使用,2.x原有的不需要 - 3.x和2.x的生命周期函数不要一起使用
onRenderTracked
,onRenderTriggered
跟踪发生变化的值,调试用
onBeforeMount(() => {
console.log('挂载前')
})
onMounted(() => {
console.log('挂载完成')
})
onBeforeUpdate(() => {
console.log('数据更新前')
})
onUpdated(() => {
console.log('数据更新完成')
})
onBeforeUnmount(() => {
console.log('卸载组件前')
})
onUnmounted(() => {
console.log('卸载组件完成')
})
watch
//第一个参数数组,是要监视的值,发生变化则触发钩子,数组里是getter格式函数
watch([() => data.overText, () => data.selectedGirl], (newVal, oddVal) => {
if (newVal[0] !== oddVal[0]) {
document.title = newVal[0]
}
})
toRefs()
用于将被reactive()
建造出来的响应对象变为普通对象,但对象里的属性都具有响应式。- Suspense 异步组件
<template>
<h2>{{ name }}</h2>
<h2>{{ age }}</h2>
<h2>{{ gender }}</h2>
</template>
<script lang="ts">
import axios from "axios";
import {toRefs, reactive} from 'vue'
export default {
name: "AsyncUserInfo",
async setup() {
try {
const res = await axios.get('http://localhost:3000')
const data = reactive(res.data)
return {...toRefs(data)}
} catch (e) {
console.log(e.message)
}
}
}
</script>
<style scoped>
</style>
<Suspense>
<template #default>
<async-user-info/>
</template>
<template #fallback>
<h2>loading...</h2>
</template>
</Suspense>
Teleport
将组件挂载到某个DOM节点上,而不一定是#app
上- CSS 会独立,不受’#app’的影响。(毕竟没有挂载到
#app
)
- CSS 会独立,不受’#app’的影响。(毕竟没有挂载到
- 计算属性
import {defineComponent, reactive, computed, toRefs} from 'vue';
interface User {
name: string,
age: number,
score: number,
pet: {
name: string,
type: string
}
}
export default defineComponent({
name: 'App',
setup() {
const userinfo: User = reactive({
name: 'zed',
age: 18,
score: 60,
pet: {
name: 'jeff',
type: 'cat'
}
})
const gt60 = computed(() => {
return userinfo.score >= 60
})
const introduce = computed(() => {
return `${userinfo.name},今年${userinfo.age}岁,我的宠物叫${userinfo.pet.name},是一只${userinfo.pet.type}`
})
return {...toRefs(userinfo), gt60, introduce}
}
});
readonly
- 无法修改ac,尝试修改的话,vue会抛出警告
const article = reactive({
title: '错把妻子当帽子',
content: '神经病例'
})
const ac = readonly(article)
props
export default {
props: {title: String},
setup(props: any) {
const titleP = ref(`这是一个标题:${props.title}`)
return {titleP}
}
provide inject
- 父级向后代传递数据
- 注意!在后代组件中可以修改父级组件所传递的数据,且会响应式地影响到父级数据
- 当使用响应式 provide / inject 值时,建议尽可能,在提供者内保持响应式 property 的任何更改。
- 然而,有时我们需要在注入数据的组件内部更新 inject 的数据。在这种情况下,我们建议 provide 一个方法来负责改变响应式 property。此时,本质上改变的还是父组件的数据。
- 最后,如果要确保通过 provide 传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用 readonly。
- 父组件中
setup() {
const article = reactive({
title: '错把妻子当帽子',
content: '神经病例'
})
const updateFoo = ()=>{
foo.value = '111'
}
let foo = ref('你好')
provide('article', readonly(article))
provide('foo', readonly(foo))
provide('updateFoo',updateFoo)
return {foo, article}
}
- 子组件中
setup() {
let foo = inject('foo')
let article = inject('article')
const updateFoo = inject('updateFoo')
return {foo, article, updateFoo}
}
- 实现接口的方法
reactive
来说有三种ref
只能用泛型
//1.泛型
const book = reactive<Book>({
title: 'title',
author: 'author'
})
//2.断言
const book = reactive({
title: 'title',
author: 'author'
}) as Book
//3. 类型声明
const book:Book = reactive({
title: 'title',
author: 'author'
})
//ref 只能 泛型
const title = ref<string>('这是一个标题')
- 动态路由
- 参数
//路由配置
path: '/article/:aid'
//跳转配置
<li v-for="(item,index) in list" :key="index">
<router-link :to="`/article/${index}`">{{ item }}</router-link>
</li>
//如何获取
<h2>我是{{$route.params.aid}}文章页面</h2>
- get传值
//路由配置
path: '/article'
//跳转配置
<router-link :to="`/article?aid=${index}`">{{ item }}</router-link>
//如何获取
<h2>我是{{$route.query.aid}}文章页面</h2>
- 函数传值
- 当你点击 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)。
<button @click="$router.push('/')">home</button>
<!-- 传值 这种方式会把键值对拼接到url后面,地址栏中会看到 -->
<button @click="$router.push({path:'/article',query:{aid:3}})">home</button>
<!-- 命名的路由,不会把键值对拼接到url上,params属性不能与path同时使用,否则params会失效 -->
<button @click="$router.push({name:'home',params:{uid:3}})">home</button>
<!-- router-link配置动态路由的另一种方式 -->
<li v-for="(item,index) in list" :key="index">
<router-link :to="{name:'article',params:{aid:index}}">{{ item }}</router-link>
</li>
- 嵌套路由
children
中的path
,不需要加/
redirect
,写成redirect: /user/userlist
vuex
在组合式API,即setup()
中的使用- 不能通过
this.$store
来获取,要先引入useStore
,然后创建实例,通过实例来获取其中的方法和属性 - 获取的属性要使用计算属性定义在
setup()
中,才能获得响应式 - 虽然
- 不能通过
import { useStore } from 'vuex'
setup(){
const store = useStore()
}
vuex
在ts中的写法
import {createStore} from "vuex";
const store = createStore({
state: {
authName: 'zed',
bookList: ['错把妻子当帽子', '三体', 'js高级程序设计第三版', '撒哈拉的故事']
},
mutations: {
changeName(state, name) {
state.authName = name
}
}
})
export default store
- 计算属性的值是只读的
//尝试改变返回简单值得计算属性的值,vue会抛出警告
//Write operation failed: computed value is readonly
ref
- 在给
name
赋值时,如果不加.value
,那么新添加的book
的name
都会绑定同一个name
- 在给
let name = ref('')
books.value.unshift({id: id++, name: name.value, price: 127})
- 如果在
async setup
中使用生命周期函数,要放在第一个await
之前 setup(props, context)
,第二个参数中的emit
即为vue2中的this.$emit
,可用结构的语法写,即setup(props, { emit })
- sticky 定位
sticky 英文字面意思是粘,粘贴,所以可以把它称之为粘性定位。position: sticky; 基于用户的滚动位置来定位。粘性定位的元素是依赖于用户的滚动,在 position:relative 与 position:fixed 定位之间切换。它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置。 - better-scroll 插件
<div class="wrapper">
<!-- 整体盒子,需要设置`overflow: hidden`以及宽高 -->
<div class="content">
<!-- 这里放置需要滚动的部分 -->
</div>
<!-- 在wrapper内部,content外部中的DOM,会被忽略 -->
</div>
- DOM元素高度发生变化,就要调用实例的
refresh
方法
- vant的使用
$ npm i vant@next
- 如果要按需引入,执行
$ npm i babel-plugin-import -D
main.ts
中引入import 'vant/lib/index.css'
- 在局部组件中引入
import {Swipe, SwipeItem} from "vant";
,并在这个组件中注册子组件components: {[Swipe.name]: Swipe, [SwipeItem.name]: SwipeItem}
- 想要全局引入
vant
,可以在main.ts
中引入并配置- vant配置图片懒加载,则要配置
Lazyload
,且将项目中需要懒加载的图片src
改为v-lazy
- vant配置图片懒加载,则要配置
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'vant/lib/index.css'
import {Lazyload, SwipeItem, Swipe} from 'vant'
createApp(App)
.use(Lazyload, {
loading: require('./assets/img/book.svg')
})
.use(Swipe)
.use(SwipeItem)
.use(store).use(router)
.mount('#app')
- vant徽标的使用
- 使用
van-badge
标签包裹需要徽标的图标,指定内容长度和最大长度
- 使用
<van-badge :content="20" max="9">
<i class="iconfont icon-gouwuche2"></i>
</van-badge>
v-bind
绑定动态参数- 动态参数的缩写 (2.6.0+)
<a :[myHref]="myLink"></a>
myHref
是在data
中的动态属性名
@click='fn(arg1,$event)'
arg1
是自定义参数$event
是鼠标事件
@click='fn1(),fn2(),fn3()'
- 一个元素可以一次绑定多个触发函数
- 可以使用计算属性监听数据变化
- 也可以用
watch
监听数据变化,但是比较耗费性能 - 在 Vue3.x 中,组件现在支持有多个根节点
- 组件传值 this props $ref $parents 单向数据流 修改
7.1 子访问父- props
0.props:[key1,key2...]
只能传值,无验证功能,可以改为props:{}
- 传递的数据如果不是静态字符串的话,那么属性名要加上
v-bind
- 如果传输
this
,则是传输的是父组件的实例,可以访问到所有属性和方法 - 单向数据流,子组件无法修改父组件传来的值,父组件的值发生更新,那么子组件中也会更新
- 注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
- 注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
- 传递的数据如果不是静态字符串的话,那么属性名要加上
- $parents
- 获取到的是父组件的实例,可以访问属性和方法
- 可以改变父组件的属性和函数
7.2 父访问子
- $refs
- 获取到的是子组件的实例,可以访问属性和方法
- 可以改变子组件的属性和函数
- $emit 自定义事件传递
- 无法改变子组件的数据
- 提交的时候,可以对数据进行验证 emits,如果违反验证规则会抛出警告
- 官方推荐使用连词符
-
来命名事件,即send-msg
7.3 兄弟组件
- 中介父组件
- 第三方库
mitt
- props
- 全局属性
// 之前(Vue 2.x)
Vue.prototype.$http = () => {}
// 之后(Vue 3.x)
const app = Vue.createApp({})
app.config.globalProperties.$http = () => {}
- vuex
// @/stores/index.ts中的写法
import Vue from "vue";
import Vuex from "vuex"
import ActionHelper from "@/stores/ActionHelper";
Vue.use(Vuex)
export default new Vuex.Store({
state: {
globalProperty: '全局属性',
ah: new ActionHelper()
},
mutations: {
logProperty(state) {
console.log(state.globalProperty)
}
}
})
// main.js 中的写法
import Vue from 'vue'
import App from './App.vue'
import store from './stores'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store
}).$mount('#app')
//使用方法
fn() {
alert(this.$store.state.globalProperty)
this.$store.commit('logProperty')
}
结语
如果对你有帮助的话,请点一个赞吧