学习笔记-随记

129 阅读2分钟

**************** vue2 和 vue3 区别 ****************

  1. v-if 与 v-for 的优先级对比

    2.x 版本中  v-for > v-if
    3.x 版本中  v-if  > v-for
    
  2. v-for 中的 Ref 数组

    vue2.x 会自动把ref填充内容
    vue3.x 需要手动添加
    	<ul>
          <li v-for='item in 5' :key='item' :ref="setItemRef">
            {{ item }}
          </li>
        </ul>
    
        methods:{
        	setItemRef(el){
        		this.arr.push( el );
        	}
    	}
    
  3. $children

    vue2.x :  访问当前实例的子组件
    
    vue3.x :  在 3.x 中,$children 已被移除,且不再支持。
    
    	设置:<HelloWorld msg="Welcome" ref='hw'/>
    
    	访问:this.$refs.hw 
    
  4. setup

    4.1 是什么 : 组合式 API

    4.2 来解决什么问题 : 使用 (data、computed、methods、watch) 组件选项来组织逻辑通常都很有效。然而,当我们的组件开始变得更大时,逻辑关注点的列表也会增长。尤其对于那些一开始没有编写这些组件的人来说,这会导致组件难以阅读和理解。

    4.3 响应区别:

     vue2.x : Object.defineProperty()
    
     vue3.x : Proxy 
    
     1. Object.defineProperty()存在的问题
    
     	1. 不能监听数组的变化
     	2. 必须遍历对象的每一个属性
    
     2. Proxy 不需要遍历
    

    4.4 使用渲染函数:

     ref  :  就是定义数据的    		简单类型
    
     reactive  :  就是定义数据的  	复杂类型
    

    4.5 setup语法糖插件 : unplugin-auto-import

     解决场景 : 在组件中开发无需每次都引入 import { ref }..
    
     1. 下载安装
    
     	npm i unplugin-auto-import -D
    
     2. 配置:vite.config.js中
    
     	import AutoImport from 'unplugin-auto-import/vite'
     	export default defineConfig({
     	  plugins: [
     	  	AutoImport({
     	  		imports:['vue','vue-router'],//自动导入vue和vue-router相关函数
                            eslintrc: {
                                     enabled: false, // 默认false, true启用。生成一次就可以,避免每次工程启动都生成
                                     filepath: './.eslintrc-auto-import.json', // 生成json文件
                                     globalsPropValue: true,
                             },
                             dts:'./auto-imports.d.ts'
     	  	})
     	  ],
     	})
                     
                     
             3.配置:eslintrc.js引入该文件
             
                  extends: [
                 './.eslintrc-auto-import.json'
               ],
             4.tsconfig.json
                 "include": ["auto-imports.d.ts"]
    
             
            
    

原文链接:blog.csdn.net/qq_35317490…

  4.5 setup语法糖插件 : vite-plugin-vue-setup-extend
  
            解决场景 : setup增加name属性

	1. 下载安装

		npm i vite-plugin-vue-setup-extend -D

	2. 配置:vite.config.jsimport VueSetupExtend from "vite-plugin-vue-setup-extend";
		export default defineConfig({
		  plugins: [
		  	VueSetupExtend(),
		  ],
		})
               

4.6 toRefs

	toRefs 函数 来完成数据的解构

4.7 computed

	1let obj = reactive({
		  name:'张三',
		  age:18,
		  str:computed(()=>{
		    return obj.name.slice(1,2)
		  })
		})

	2let msgChange = computed(()=>{
		  return msg.value.slice(1,3);
		})

	3let msgChange = computed({
		  get(){
		    return msg.value.slice(1,3);
		  },
		  set(){
		    console.log('设置了')
		  }
		})


4.8 watch

	vue2.x :

		watch:{
			obj:{
				handler(newVal , oldVal){
					console.log( newVal , oldVal  )
				},
				immediate:true,
				deep:true
			}
		}

	vue3.x :

		1> 监听数据数据「初始化监听」

			watch( msg , (newVal,oldVal)=>{
				console.log(  newVal,oldVal )
			},{
				immediate:true
			})

		2> 监听多个数据「一起监听」

			watch([msg,str],(newVal,oldVal)=>{
				console.log(  newVal,oldVal )
			},{
				immediate:true
			})

		3> 监听“对象”中某个对象

			watch( ()=>obj.arr , (newVal,oldVal)=>{
				console.log( newVal,oldVal )
			})

		4> 立即执行监听函数

			watchEffect(()=>{
				console.log(  msg.value  )
			})

	参考链接:https://v3.cn.vuejs.org/api/computed-watch-api.html#watcheffect


4.9 组件 : 父 传 子

	1. 父

		<template>
			<div>
				<List :msg='msg'></List>
			</div>
		</template>

		<script setup>
		import List from '../components/List.vue'
		let msg = ref('这是父传过去的数据');
		</script>

	2. 子

		<template>
			<div> 
				这是子组件 ==> {{ msg }}
			</div>
		</template>

		<script setup>
		defineProps({
			msg:{
				type:String,
				default:'1111'
			}
		})
		</script>

4.10 组件 :子 传 父 

	子:
		<template>
			<div> 
				这是子组件 ==> {{ num }}
				<button @click='changeNum'>按钮</button>
			</div>
		</template>

		<script setup lang='ts'>
		let num = ref(200);

		const emit = defineEmits<{
		  (e: 'fn', id: number): void
		}>()

		const changeNum = ()=>{
			emit('fn',num)
		}	
		</script>

	父:
		<template>
			<div>
				<List @fn='changeHome'></List>
			</div>
		</template>

		<script setup>
		import List from '../components/List.vue'
		const changeHome = (n)=>{
			console.log( n.value );
		}
		</script>

4.11 v-model传值

	父:
		<List v-model:num='num'></List>
		<script setup>
		import List from '../components/List.vue'
		let num = ref(1);
		</script>
	子:
		const props = defineProps({
			num:{
				type:Number,
				default:100
			}
		})
		const emit = defineEmits(['update:num'])
		const btn = ()=>{
			emit('update:num',200);
		}

4.12 兄弟组件之间的传值

	1》下载安装

		npm install mitt -S

	2》plugins/Bus.js

		import mitt from 'mitt';
		const emitter = mitt()
		export default emitter;

	3》A组件

		emitter.emit('fn',str);

	4》B组件

		emitter.on('fn',e=>{
			s.value = e.value;
		})

5. 生命周期

5.1 选项式 API

	beforeCreate ...

5.2 setup 组合式API

	注意:没有beforeCreate和created
	其他生命周期要使用前面加"on" 例如:onMounted

参考链接:https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html

6. 路由

useRoute  ==> this.$route

useRouter ==> this.$router

7. 插槽

匿名插槽
	父:
		<A>
			这是xxxxx数据
			这是yyyyy数据
		</A>

	子:
		<header>
			<div>头部</div>
			<slot></slot>
		</header>

		<footer>
			<div>底部</div>
			<slot></slot>
		</footer>
具名插槽
	父:
		<A>
			<template v-slot:xxx>
				这是xxxxx数据
			</template>

			<template v-slot:yyy>
				这是yyyyy数据
			</template>
		</A>

		***简写:<template #xxx>
	子:
		<header>
			<div>头部</div>
			<slot name='xxx'></slot>
			<slot name='yyy'></slot>
		</header>

		<footer>
			<div>底部</div>
			<slot name='xxx'></slot>
		</footer>

作用域插槽

	父:
		<template v-slot='{data}'>
			{{ data.name }} --> {{ data.age }}
		</template>

		简写:<template #default='{data}'>
	子:
		<div v-for='item in list' :key='item.id'>
			<slot :data='item'></slot>
		</div>

动态插槽:

	说了就是通过数据进行切换

	父:

		<template #[xxx]>
			这是xxxxx数据
		</template>

		<script setup>
		let xxx = ref('xxx');
		</script>

8. Teleport : 传送

<teleport to='#container'></teleport>
<teleport to='.main'></teleport>
<teleport to='body'></teleport>

***必须传送到有这个dom的内容【顺序】

9. 动态组件

<component :is="动态去切换组件"></component>

10. 异步组件

***提升性能

vueuse : https://vueuse.org/core/useintersectionobserver/

10.1 使用场景1

	组件按需引入:当用户访问到了组件再去加载该组件

		<template>
			<div ref='target'>
				<C v-if='targetIsVisible'></C>
			</div>
		</template>

		<script setup>
		import { useIntersectionObserver } from '@vueuse/core'

		const C = defineAsyncComponent(() =>
		  import('../components/C.vue')
		)

		const target = ref(null);
		const targetIsVisible = ref(false);

		const { stop } = useIntersectionObserver(
		  target,
		  ([{ isIntersecting }]) => {
		  	if( isIntersecting ) {
		  		targetIsVisible.value = isIntersecting
		  	}
		  },
		)
		</script>

10.2 使用场景2 

	<Suspense>
		<template #default>
			<A></A>
		</template>
		<template #fallback>
			加载中...
		</template>
	</Suspense>

	<script setup>
	const A = defineAsyncComponent(() =>
	  import('../components/A.vue')
	)
	</script>


10.3 打包分包处理

	npm run build打包完成后,异步组件有单独的js文件,是从主体js分包出来的

	A.c7d21c1a.js
	C.91709cb2.js

11. Mixin : 混入

是什么:来分发 Vue 组件中的可复用功能

11.1 setup写法
	mixin.js
		import { ref } from 'vue'
		export default function(){

			let num = ref(1);
			let fav = ref(false);

			let favBtn = ()=>{
				num.value += 1;
				fav.value = true;
				setTimeout(()=>{
					fav.value = false;
				},2000)
			}

			return {
				num,
				fav,
				favBtn
			}

		}

	组件:
		<template>
			<div>
				<h1>A组件</h1>
				{{ num }}
				<button @click='favBtn'>
					{{ fav ? '收藏中...' : '收藏' }}
				</button>
			</div>
		</template>

		<script setup>
		import mixin from '../mixins/mixin.js'
		let { num , fav , favBtn } = mixin();
		</script>


11.2 选项式api写法

	mixin:
		export const fav = {
			data () {
				return {
					num:10
				}
			},
			methods:{
				favBtn( params ){
					this.num += params;
				}
			}
		}

	组件:
		<template>
			<div>
				<h1>A组件</h1>
				{{ num }}
				<button @click='favBtn(1)'>按钮</button>
			</div>
		</template>

		<script type="text/javascript">
		import { fav } from '../mixins/mixin.js'
		export default{
			data () {
				return {
					str:'你好'
				}
			},
			mixins:[fav]
		}
		</script>

12. Provide / Inject ==> 依赖注入

提供:
	<script setup>
	provide('changeNum', num );
	</script>

注入:
	<template>
		<div>
			<h1>B组件</h1>
			{{ bNum }}
		</div>
	</template>

	<script setup>
	const bNum = inject('changeNum');
	</script>

13. Vuex

13.1 state:
	let num = computed( ()=> store.state.num );
13.2 getters:
	let total = computed( ()=> store.getters.total );
13.3 mutations:
	store.commit('xxx')
13.4 actions:
	store.dispatch( 'xxx' )
13.5 modules: 

	和之前的版本使用一样

13.6 Vuex持久化存储【插件】

	1. npm i vuex-persistedstate -S

	2. import persistedState from 'vuex-persistedstate'

	3. export default createStore({
	  modules: {
	  	user
	  },
	  plugins:[persistedState({
	  	key:'xiaoluxian',
	  	paths:['user']
	  })]
	});

14. Pinia

14.1 Vuex和pinia的区别

	参考网址: https://github.com/vuejs/rfcs/pull/271 

	1. pinia没有mutations,只有:state、getters、actions
	2. pinia分模块不需要modules(之前vuex分模块需要modules)
	3. pinia体积更小(性能更好)
	4. pinia可以直接修改state数据

14.2 pinia使用

	官方网址:https://pinia.vuejs.org/

	具体使用:https://xuexiluxian.cn/blog/detail/242b0ed71feb412991f04d448fc86636

14.3 pinia持久化存储

	参考链接:https://xuexiluxian.cn/blog/detail/acebacd99612447e8c80dcf6354240f6
	

15. 设置代理解决跨域问题

参考文章:https://xuexiluxian.cn/blog/detail/01f62baa85b7431992586b4689a9b07a

API参考链接:https://staging-cn.vuejs.org/api/#onmounted