vue3初探---vue3新特性学习

vue3初探—vue3新特性学习

一、vue3初探—vue3新特性学习

二、vue3初探—在vue3和vuex4.x中使用typescript

三、vue3初探----(vue3项目)vuex4.x中使用typescript最终写法

四、在三中用到的一些TypeScript中的一些高阶类型 Omit Pick ReturnType Parameters

五、vue3初探----项目构建

六、vue3初探----vue3的一些变化

项目构建

vite

npm init @vitejs/app demo-vue3-vite
选择vue,选择vue-ts
cd demo-vue3-vite
npm install
npm run dev

vue3的新特性

向后兼容:兼容vue2的写法

性能提升

TypeScript的支持

Composition API

在这里插入图片描述

当然还有其他改变,可查看官方文档 https://v3.cn.vuejs.org/guide/migration/introduction.html#%E5%80%BC%E5%BE%97%E6%B3%A8%E6%84%8F%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7

Composition API

setup函数

setup 函数是一个新的组件选项。作为在组件内使用 Composition API 的入口点。

setup会在 beforeCreate前被调用,同时在vue3中setup代替了beforeCreate和created

网上许多文章认为setup执行时间在beforeCreatecreated 之间但试验结果setup是在beforeCreate之前执行

<script>
export default {
  setup() {
    console.log('setup')
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
  created() {
    console.log('created')
  },
}
</script>

在这里插入图片描述

vue3中的生命周期函数,可以按需导入到组件中,且只能在 setup() 函数中使用

<script>
import { onMounted, onUpdated, onUnmounted } from 'vue';
 
export default {
  setup() {
    onMounted(() => {
      console.log('mounted!');
    });
    onUpdated(() => {
      console.log('updated!');
    });
    onUnmounted(() => {
      console.log('unmounted!');
    });
    return {};
  }
};
</script>

参数

setup有连个参数 props和context

props 接收当前组件props选项的值,即获取父组件传递过来的参数

context,接收一个上下文对象,该对象中包含了一些在vue 2.x 中需要通过 this 才能访问到属性

<script lang="ts">
import {defineComponent } from 'vue';

export default defineComponent({
    props: {
        name: String
    },
    setup(props, context) {
        context.attrs;
        console.log(props.name);
        context.slots;
        context.emit;
    }
});
</script>

返回值

函数返回的内容可作为模板渲染

<template>
    <p>{{name}}</p>
</template>  
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
    setup() {
        let name = ref('guoang');
        return {
            name
        };
    }
});
</script>

getCurrentInstance

支持访问内部组件实例

在这里插入图片描述

 const internalInstance = getCurrentInstance() 

getCurrentInstance在await之后调用无法获取到内部组件实例

因为vue在执行时不会等待setup执行完毕,而在setup后面上下文会被设为null所以在await之后获取到是null

export default defineComponent({
	async setup() {
		const result = ref('')
		result.value = await resultValue()
        const internalInstance = getCurrentInstance() 
        console.log('await之后getCurrentInstance()获取不到',internalInstance) //internalInstance = null
		return {
			result,
		}
	},
})

在这里插入图片描述

响应式api

响应式api

推荐文章:深入理解 Vue3 Reactivity API

reactive

reactive()函数接收一个普通对象,返回该普通对象的响应式代理对象

reactive()接收一个泛型来定义他的类型

<template>
    <p>{{user.name}}</p>
    <p>{{user.age}}</p>
</template>

<script  lang="ts">
interface User {
    name: string;
    age: number;
}
import { reactive, defineComponent } from 'vue';
export default defineComponent({
    setup() {
        let user = reactive<User>({
            name: 'guaong',
            age: 0
        });
        return {
            user
        };
    }
});
</script>

如果reactive生成的数据如果被展开就失去了响应性

 setup() {
        let state = reactive({ count: 0 });
        function add() {
            state.count += 1;
        }
        return { ...state };
 }
toRefs

toRefs()函数可以将reactive()创建出来的响应式对象,转换为普通对象,只不过这个对象上的每个属性节点,都是ref响应式数据

 setup() {
        let state = reactive({ count: 0 });
        function add() {
            state.count += 1;
        }
        return { ...toRefs(state) };
 }

ref

reactive()负责复杂的数据结构,ref()则可以把基本的数据结构包装成响应式

ref()函数接收一个参数值,返回一个响应式的数据对象。该对象只包含一个指向内部值的 .value 属性

在模板中访问时,无需通过.value属性,它会自动展开

ref()接收一个泛型来定义他的类型

<template>
    <!-- 无需加value -->
    <h2>{{num}}</h2>
    <button @click="add">累加</button>
</template>
<script lang="ts">
import { ref,defineComponent } from 'vue';

export default defineComponent( {
    setup() {
        let num = ref(2);
        function add() {
            num.value += 1; //需要加value
        }
        return { add, num };
    }
});
</script>
toRef

创建一个ref类型数据, 并和以前的数据关联

备注

  1.toRef
  创建一个ref类型数据, 并和以前的数据关联
  2.toRefs
  批量创建ref类型数据, 并和以前数据关联
  3.toRef和ref区别
  ref-创建出来的数据和以前无关(复制)
  toRef-创建出来的数据和以前的有关(引用)
  ref-数据变化会自动更新界面
  toRef-数据变化不会自动更新界面

computed

computed() 函数用来创建计算属性,函数的返回值是一个 ref 的实例

    setup() {
        let num = ref(2);
        function add() {
            num.value += 1;
        }
        let double = computed(() => num.value * 2);
        return { add, double, num };
    }

或者,接受一个具有 getset 函数的对象,用来创建可写的 ref 对象。

const count= ref(2);
const newCount = computed({
  get: () => count.value,
  set: val => {
    count.value = val
  }
})
watchEffect

立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

const count = ref(0)

watchEffect(() => console.log(count.value))

触发时机

const count = ref(0)    
watchEffect(() => {
      const text = count.value ;
      console.log(text);
    }, {
      flush: 'post' // 'pre'组件更新前运行,'post'组件更新后运行,默认为'pre'
    }
watch

参数watch第一个参数传入的 要监听的对象,第二个参数是回调函数,监听的对象改变就会执行回调函数,第三个参数深度监听或立即执行的配置

返回值 watch返回一个方法调用可停止监听

const unwatch = watch(
            () => state.count,
            (newVal, oldVal) => {
                console.log(oldVal);
                console.log(newVal);
            },
            { deep: true, imediate: true }
        );
        const stop = () => {
            unwatch();
        };

在这里插入图片描述

也可以监听多个对象

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  /* ... */
})
vue3的响应式系统

vue3将响应式系统完成独立的一个包**@vue/reactivity**,也就是说ref,reactive,effect… 这些方法可以用在任何项目中(浏览器,node),这些方法不再依赖于vue,只需要import { reactive, effect } from “@vue/reactivity”;就可以使用

封装一个操作localStorage的方法

import { reactive, effect } from "@vue/reactivity";

/**
 * @Author: guoang
 * @description: 操作localStorage
 * @param key 需要获取localStorage的key
 * @param defaultValue 默认值,获取不到localStorage对应key的数据则返回默认值
 * @return 一个响应式对象
 */
export default function newStorage<T extends {}>(key: string, defaultValue = {}): Partial<T>  {
    let data: Partial<T>= reactive({});
    Object.assign(data, window.localStorage.getItem(key) && JSON.parse(<string>(localStorage.getItem(key))) || defaultValue);
    //在data改变时会触发effect中的方法重新设置localStorage
    effect(() => {
        window.localStorage.setItem(key, JSON.stringify(data))
    });
    return data;
}

使用

<template>
    <label>姓名:</label>
    <span>{{userInfo.name}}</span>
    <label>年龄:</label>
    <span>{{userInfo.age}}</span>
    <button @click="changeUserInfo">changeUserInfo</button>
</template>
<script lang="ts">
import { reactive, computed, ref, onMounted } from 'vue';
import newStorage from './newStorage';
interface UserInfo{
    name: string
    age: number|string
}
export default {
    setup() {
        let userInfo = newStorage<UserInfo>('userInfo', {
            name: '名称',
            age: 100
        });
        const changeUserInfo = () => {
            userInfo.name = 'guoang';
            userInfo.age = '120';
        };
        return { userInfo, changeUserInfo };
    }
};
</script>

效果

在这里插入图片描述

点击changeUserInfo更新视图同时更新localStorage

在这里插入图片描述

模板 Refs

在vue2.X中使用vm.$refs

在vue3中

<template>
    <div ref="divRef"></div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
export default defineComponent( {
    setup() {
        // 创建一个值为null的ref的对象,并返回
        const divRef = ref(null);
        console.log(divRef)
        return{
            divRef 
        }
    }
});
</script>

setup语法糖

<template>
    <Foo />
    <div v-click-outside />
</template>
<script setup>
import { defineProps, defineEmit, useContext } from 'vue'; //导入组件直接使用
import Foo from './Foo.vue';
import vClickOutside from 'v-click-outside'; //导入指令直接使用    *导入指令前面必须加v
// 书写组合式 api 就像在正常的 setup 中一般,但是不需要进行手动地进行 return
//const count = ref(0) 也可以这样
ref: count = 1;
const inc = () => {
    // 直接操作变量 不用.value
    count++;
};
// 使用 props
const props = defineProps({
    foo: String
});
//使用 emit
const emit = defineEmits(['update', 'delete']);
// 获取 slots 和 attrs
const { slots, attrs } = useContext();
</script>

vue新组件Teleport Fragment Suspense

Teleport

Teleport 提供了一种简单的方法,使我们可以控制要在DOM中哪个父对象下呈现HTML。

index.html

<body>
		<div id="app"></div>
		<div id="web"></div>
		<script type="module" src="/src/main.ts"></script>
	</body>

vue中

<template>
    <div>
        我在id=app
    </div>
    <!-- to 属性就是目标位置 -->
    <teleport to="#web">
        <div>我在id=web</div>
    </teleport>
</template>

渲染结果

在这里插入图片描述

Fragment

在vue2中创建一个Vue组件,那么它只能有一个根节点,多了一层嵌套

<template>
    <div>
        <div></div>
        <div></div>
    </div>
</template>

在vue3中会有一个名为 Fragment 的虚拟元素,他并不会呈现

<template>
    <div></div>
    <div></div>
</template>
Suspense

Suspense异步组件

setup 中返回一个 Promise 对象

defineComponent 包裹要导出的实例对象

<template>
    <h1>{{ result }}</h1>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
    async setup() {
        const result = ref('');
        result.value = await resultValue();
        return {
            result
        };
    }
});
const resultValue = (): Promise<string> => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('HelloWorld');
        }, 3000);
    });
};
</script>

app.vue

使用 <Suspense> 包裹所有异步组件相关代码

<Suspense> 下 <template #default> 插槽包裹异步组件

<Suspense> 下 <template #fallback> 插槽包裹渲染异步组件之前的内容

<template>
    <Suspense>
        <template #default>
            <HelloWorld></HelloWorld>
        </template>
        <template #fallback>
            <h1>Loading...</h1>
        </template>
    </Suspense>
</template>

<script lang="ts" setup>
import HelloWorld from './components/HelloWorld.vue';
</script>

在这里插入图片描述
三秒后
在这里插入图片描述

注意点

解构props属性,如果直接在 setup 中引用,必须要加 toRefs

    const { users } = toRefs(props)

setup语法糖中导入指令前面必须加v

import vClickOutside from 'v-click-outside'; //导入指令直接使用    *导入指令前面必须加v(vClickOutside)
注意点

解构props属性,如果直接在 setup 中引用,必须要加 toRefs

const { users } = toRefs(props)

setup语法糖中导入指令前面必须加v

import vClickOutside from 'v-click-outside'; //导入指令直接使用    *导入指令前面必须加v

watchEffect() 与 effect() 的区别

watchEffect() 会维护与组件实例以及组件状态(是否被卸载等)的关系,如果一个组件被卸载,那么 watchEffect() 也将被 stop,但 effect() 则不会,普通开发中不推荐直接用 effect() 啦,使用 watchEffect() 就好了

  • 15
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
条件语句 v-if ,v-else,v-else-if。 后两者必须放在v-if之后 循环语句 v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。 Computed VS methods 我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。 事件修饰符 Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或 event.stopPropagation()。Vue.js通过由点(.)表示的指令后缀来调用修饰符。 <!-- 阻止单击事件冒泡 --> <a stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件侦听器时使用事件捕获模式 --> <div v-on:click.capture="doThis">...</div> <!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 --> <div v-on:click.self="doThat">...</div> <!-- click 事件只能点击一次,2.1.4版本新增 --> <a 按键修饰符 为最常用的按键提供了别名: <input v-on:keyup.enter="submit"> <!-- 缩写语法 --> <input @keyup.enter="submit"> Vue.js为最常用的两个指令v-bind和v-on提供了缩写方式。v-bind指令可以缩写为一个冒号,v-on指令可以缩写为@符号。 全部的按键别名: .enter .tab .delete (捕获 "删除" 和 "退格" 键) .esc .space .up .down .left .right .ctrl .alt .shift .meta 实例 组件部分不太会,em...... 钩子函数 指令定义函数提供了几个钩子函数(可选): bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。 inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。 update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。 componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。 unbind: 只调用一次, 指令与元素解绑时调用。 钩子函数的参数有: el: 指令所绑定的元素,可以用来直接操作 DOM 。 binding: 一个对象,包含以下属性: name: 指令名,不包括 v- 前缀。 value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2。 oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。 expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。 arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"。 modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。 vnode: Vue 编译生成的虚拟节点。 oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。 样式叠加测试文件:test2/addStyle.html 属性覆盖测试文件:test2/cover.html 自定义组件测试文件:test2/customComponent.html get请求测试文件:test2/get.html post请求测试文件:test2/post.html vue初探:test2/helloVue.html,test2/helloVue2.html input 和 textarea 元素中使用 v-model 实现双向数据绑定:test2/inputAndtextarea.html 两个按钮用于切换不同的列表布局:test2/layout.html 导航测试:test2/navigation.html 订单列表:test2/orderList.html 实时变更:test2/real-time-change.html 模糊搜索:test2/search.html 购物车:test2/shoppingCart.html 双向绑定:test2/two-way-binding.html 字符转换:test2/upperCase.html class属性绑定:test2/v-bind.html href 属性绑定:test2/v-test.html vue路由:test2/vueRouter.html watch监听时间:watchJianTing.html

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值