简介
vue3.0 向下兼容 vue2.x 版本,优化了主要核心双向绑定原理和体积大小,并且更加友好的兼容 ts 语法。
Vue3
两种构建方式
第一种方式 vite
npm init vite@latest√ Project name: ... vite-demo ? Select a framework: » - Use arrow-keys. Return to submit. Vanilla > 》Vue > React > Preact > Lit > Svelte》JavaScript TypeScript Customize with create-vue Nuxtcd vite-demo // 安装依赖 npm i // 运行项目 npm run dev
第二种方式创建 @vue/cli
// 脚手架安装 nmp i -g @vue/clivue create vue-cli-demo? Please pick a preset: vue_shop_preset ([Vue 2] babel, router, eslint) Default ([Vue 2] babel, eslint) Default (Vue 3) ([Vue 3] babel, eslint) > Manually select features // 可以走自定义安装? Please pick a preset: Manually select features ? Check the features needed for your project: (`*`) Choose Vue version (`*`) Babel ( ) TypeScript ( ) Progressive Web App (PWA) Support ( ) Router ( ) Vuex ( ) CSS Pre-processors ( ) Linter / Formatter ( ) Unit Testing ( ) E2E Testing? Please pick a preset: Manually select features ? Check the features needed for your project: Choose Vue version, Babel ? Choose a version of Vue.js that you want to start the project with (Use arrow keys) 2.x > 3.x// 走默认 ? Please pick a preset: Manually select features ? Check the features needed for your project: Choose Vue version, Babel ? Choose a version of Vue.js that you want to start the project with 3.x ? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys) > In dedicated config files > In package.json将项目运行
cd vue-cli-demo npm run serve
对比两种方式创建项目
推荐使用 vite 方式创建项目!
vite 优势如下:
- 开发环境中,无需打包操作,可快速的冷启动。
- 轻量快速的热重载(HMR)。
- 真正的按需编译,不再等待整个应用编译完成。 传统 webpack 编译:每次执行编译时,都会通过入口 entry 先去找到各个路由,再去加载每个路由各自的模块,然后会进行打包成为 bundle.js 文件,最后才通知服务器热更新。所以换句话说就是等所有文件加载就绪之后才去渲染更新页面的==》较慢
vite 编译:与传统构建不同的是,vite 会先准备好服务器更新,再去找到入口文件然后再动态的找到需要加载的路由去编译那个路由下的模块,类似于按需加载,总体体积较小且更新更快。
Vue3
基础语法
组合式API
介绍
-
将同一逻辑关注点相关的代码收集到一起,这就是组合式API(composition-api);
-
实现组合式API的入口点就是
setup
函数;
setup()
组合式api
的入口
-
setup的作用 setup是一个函数,提供了组合式api的入口 ;
-
执行时机 setup函数是在berforeCreate这个钩子函数之前执行,props属性解析之后执行 在setup函数中是不能使用this的 ;
-
两个参数 props:获取props属性中的值的 context:是一个对象,里面包含了vue实例对象创建之前的所有属性;
<template>
<div></div>
</template>
<script>
import { defineComponent, ref } from "vue";
export default defineComponent({
// 实现组合式API的入口点就是 setup 函数
setup() { // 在setup函数中, vue实例还没有开始创建 所以this是不能使用的!
console.log('setup') // 先执行
beforeCreate() {
console.log('beforeCreate') // 后执行
}
return {};
},
});
</script>
ref()
setup
中实现数据响应式
在setup中实现数据的响应式;
如果想要在 setup 函数中操作通过 ref 函数创建出来的值,必须要加一个 .value
在页面中使用需要使用 {{}}
占位解析变量使用;
<template>
<div>
<input type="text" v-model="msg" />
<div ref="divEl">{{ msg }}</div>
</div>
</template>
<script>
import { defineComponent, ref } from "vue";
export default defineComponent({
// 实现组合式API的入口点就是 setup 函数
setup() { // 在setup函数中, vue实例还没有开始创建 所以this是不能使用的!
/* 在setup中实现数据的响应式 */
// ref 方法是用来创建响应式数据; 获取数据: console.log(msg.value);
let msg = ref("hello world");
let divEl = ref();
onMounted(() => {
// 当Dom加载完毕后才会执行的生命周期函数(mounted)
console.log(divEl.value);
});
return {
msg,
divEl
};
},
});
</script>
reactive()
复杂数据类型响应式
创建对象类型(对象、数组和 Map 、 Set 这样的集合类型)的响应式对象;
ref和reactive的区别 ?
ref可以创建任何数据类型的响应式对象;reactive仅仅能创建对象类型(对象、数组和 Map 、 Set 这样的集合类型)的响应式对象;
ref如果传递的是基本数据类型的数据,返回的是响应式数据;reactive如果传递的是基本数据类型 的数据,返回的是不是响应式对象
通过ref创建出来的数据,操作的时候要加一个 .value ;但是reactive创建出来的数据不需要
<template>
<div>
<h2>Reative</h2>
<input type="text" v-model="obj.msg2">
<div>{ obj.msg2 }</div>
</div>
</template>
<script>
import { defineComponent, ref, onMounted, reactive, toRefs, computed, watch, watchEffect } from "vue";
export default defineComponent({
setup() {
/**
* reactive 创建多个响应式数据; 注意: 不能去解构, 解构后就不会具备响应式了!解构过去就是一个proxy的对象了!
* reactive仅仅能创建对象类型(对象、数组和 Map 、 Set这样的集合类型)的响应式对象;
* reactive() 方法返回一个 proxy 对象; 只有以reactive()是响应式的是因为创建出来 proxy 是响应式的!
* console.log(obj); proxy 对象
* **/
const obj = reactive({
msg2: 'hello world',
count: 0
})
return { obj };
}
})
toRefs()
解构而不会失去响应式
toRefs() 将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref()
<template>
<div>
<h2>Reative</h2>
<input type="text" v-model="msg2">
<div>{{ msg2 }}</div>
</div>
</template>
<script>
import { defineComponent, ref, onMounted, reactive, toRefs, computed, watch, watchEffect } from "vue";
export default defineComponent({
setup() {
const obj = reactive({
msg2: 'hello world',
count: 0
})
/**
* toRefs() 可以解构而不失去响应式!
* **/
// 将 reactive() 返回的 proxy对象进行解构; 解构后就是一个普通对象了; 是不能具备响应式的!
const { msg2, count } = toRefs(obj)
return { msg2, count };
}
})
</script>
computed()
计算属性
创建只读的计算属性
<template>
<div>
<h2>计算属性: 只读 </h2>
<div>{{ resverMsg }}</div>
</div>
</template>
import { defineComponent, ref, computed } from 'vue';
export default defineComponent({
setup(props, context) { // 组合式api的入口
// 计算属性: 在计算属性中传递一个函数; 将字符串反转(注:这种方操作的数据是只读属性)
let resverMsg = computed( ()=> msg.value.split('').reverse().join('') )
return {
reverseMsg
}
}
}
})
创建可读写的计算属性
<template>
<div>
<h2>可读写的计算属性: 全选返选 </h2>
全选: <input type="checkbox" v-model="chooseAll"> <br/>
<input type="checkbox" v-for="item in arr" :key="item.id" v-model="item.checked">
</div>
</template>
import { defineComponent, ref, computed } from 'vue';
export default defineComponent({
setup(props, context) { // 组合式api的入口
// 计算属性: 在计算属性中传递一个函数; 将字符串反转(注:这种方操作的数据是只读属性)
const arr = ref([
{ id:1, checked: false},
{ id:2, checked: false},
{ id:3, checked: false},
])
// 可读写的计算属性: 在计算属性中传递一个对象
const chooseAll = computed({
get() { // 获取值
// 当选框全被选中
return arr.value.every( item => item.checked)
},
set(newValue) { // 设置值
arr.value.forEach( item => item.checked = newValue)
}
})
return {
reverseMsg
}
}
}
})
watch()
监听属性
<template>
<div>
<h2> 监听属性 watch </h2>
<input type="text" v-model="msg">
</div>
</template>
import { defineComponent, ref, computed } from 'vue';
export default defineComponent({
setup(props, context) { // 组合式api的入口
// watch: 懒监听! 监听的数据改变才会被执行,数据不更改就不会触发执行!
watch(msg, (newVal, oldVal) =>{
console.log(newVal, oldVal, '91');
},
{
immediate: true // 监听数据没有发生改变也会先去执行一次
deep: true // 开启深度监听
}
)
}
}
})
watchEffect()
监听属性
-
watchEffect和watch的区别?
-
watch 是懒执行的,即只有当监听的数据发生变化时才会执行回调;
-
watchEffect 则不管监 听的数据有没有发生变化都会执行一次回调函数 watchEffect 可以自动追踪到依赖的数据;
-
当依赖的数据发生变化时就会再次执行回调函数
<template>
<div>
<h2> 监听属性 watch </h2>
<input type="text" v-model="msg">
</div>
</template>
import { defineComponent, ref, computed } from 'vue';
export default defineComponent({
setup(props, context) { // 组合式api的入口
/**
* 监听属性: vue3 新增; 不管监听数据有没有改变都会默认执行一次, 数据改变了也会自当的去响应;
* 比较智能不需要传递监听的数据!也没参数; 根据回调函数路面的代码自动最终变化的数据
* **/
watchEffect( () =>{
console.log(msg.value)
})
return { msg}
}
}
})