 
      vue3.x文档https://www.vue3js.cn/docs/zh/api/application-config.html#errorhandler
vite是一个Web开发构建工具,由于其本机ES模块导入方法,因此可以闪电般快速地提供代码。通过在终端中运行以下命令,可以使用Vite快速设置Vue项目。1.npm init vite-app
2.npm install 
vue create 项目名
注意点 (vue3)
- setup中的this指向是undefind
- beforeCreated中的this指向是proxy ,vue2中的this是vue实例
setup坑
- 使用provide与inject时,provide如果需要响应子组件,需要将rective/ref整体数据传,不能是对象里面的数据单独传(不响应),见例子 - parent.vue- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25- <div class="hello"> 
 <h2><button @click="changeMsg">修改</button>{{msg}}</h2>
 <headerbar></headerbar>
 <contentbar></contentbar>
 <footerbar></footerbar>
 </div>
 
 setup(){
 
 const data = reactive({
 msg:'这是我要传递的信息'
 });
 const methods = {
 changeMsg:function(){
 data.msg = '我被 修改了'+Math.random()
 }
 }
 provide('data',data); //子组件会实时更新,响应
 provide('msg',data.msg); //子组件只会收到1次,更新 时不将响应
 provide('changeMsgFn',methods.changeMsg);
 return {
 ...toRefs(data),
 ...methods
 }
 },- son.vue- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- setup(props) { 
 const parentData = inject("data");
 const changeMsgFn = inject("changeMsgFn");
 /* const data = reactive({
 parentData:inject('data'),
 msg:inject("msg"),
 changeMsg:inject("changeMsgFn")
 });
 console.log(data); */
 return {
 parentData,
 changeMsgFn
 };
 },- 为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 或 reactive。 - 原文参考:https://v3.cn.vuejs.org/guide/composition-api-provide-inject.html#%E4%BD%BF%E7%94%A8-inject 
setup**用法1,使用ref代替vue2中的data+methods**
| 1 | <ol> | 
| 1 | setup(){ | 
| 1 | setup(){ | 
reactive用法,使用reactive代替ref
| 1 | <ol> | 
上面代码遍历时每次都需要写liData?使用toRefs
官方说法:由于props是反应性的,您不能使用ES6解构,因为它会删除道具的反应性。
| 1 | const liData = reactive({ | 
ref与reactive的区别
ref用于创建简单的响应式数据,reactive用于创建复杂的响应式数据
setup语法糖的使用
使用setup组件自动注册,无需手动在components中注册组件,只需要引入
| 1 | <template> | 
使用setup后新增API
defineProps 用来接收父组件传来的 props
| 1 | <template> | 
defineEmits 子组件向父组件事件传递
| 1 | <template> | 
defineExpose
组件暴露出自己的属性,在父组件中可以拿到。请注意,非setup语法糖,父组件可以直接使用ref拿到子组件的属性和方法。而setup语法糖默认不会拿到任何定义属性和方法,如需要拿到使用defineExpose暴露出去
| 1 | <template> | 
vue2与vue3的生命周期
| 1 | 选件API 钩在里面 setup | 
computed
| 1 | const num1 = ref(0); | 
| 1 | const num1 = ref(0); | 
watch
| 1 | // watching a getter | 
| 1 | const firstName = ref(''); | 
假定结构如下
| 1 | const state = reactive({ count:1,info:{name:'xxx'} }); | 
- watch(state,(newVal,oldVal)=>{}) - 正常情况 异常行为监听一个object对象时newVal === oldVal
- watch(()=>state.count,(newVal,oldVal)=>{ }) - 单独监听某个值的情况
- watch([()=>state.count,()=>state.info.name],(newVal,oldVal)=>{ }); - 此时newVal= [item1(state.count的值),item2(state.info.name)的值]
- watch(()=>state.info,(newVal,oldVal)=>{ },{deep:true}) - 监听state中的某个对象时,需要手动开启deep:true深度监听,否则无法监听到state.info.name的变化时的回调
- const state = ref({ count:1,info:{name:'xxx'} });watchEffetc添加了第三个配置项immediate:true,deep:true- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 **`假定有如上的特殊情况`** 监听方法为 `watch(()=>state.value.count)` 需要使用.value
 
 //注意使用reactive时,需要在监听的对象上构造一次,如使用ref创建 的数据,可直接监听
 相关链接: https://v3.vuejs.org/guide/reactivity-computed-watchers.html#watch
 ### watchEffect
 ```javascript
 const state = reactive({
 num1:0,
 num2:0,
 sum:''
 });
 watchEffect(()=>{
 state.sum = Number(state.num1) +Number(state.num2);
 });
watchEffect比watch更加智能,类似于computed的方式,watchEffect根据里面的依赖值变化而触发回调
| 1 | const info = reactive({ | 
toRef
toRef可以将reactive某个字段单独提出来与原数据建立共同的映射,即month = person.info.money类似,通过修改toRef的值,可以直接修改reactive
| 1 | const person = reactive({ | 
toRefs
- toRefs可以将reactive定义的数据解析出来,去掉第一级 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- const person = reactive({ 
 name:'xiaoMi',
 info:{
 money:1
 }
 });
 return {
 ...toRefs(person)
 }
 /**
 <template>中可以省略person的重复写
 <template>{{name}}</template>
 /**
- toRefs将一个Reactive中的某个Object对象单独提出,与原有的数据关联 即user = person - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- const person = reactive({ 
 name:'xiaoMi',
 info:{
 money:1
 }
 })
 const user = toRefs(person);
 const editName = ()=>{
 user.name.value +='!'
 }
readonly
接受一个对象 (响应式或纯对象) 或 ref 并返回原始对象的只读代理。只读代理是深层的:任何被访问的嵌套 property 也是只读的。
shallowReactive
创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (暴露原始值)
markRaw
| 1 | const person = reactive({ | 
使用markRaw标记的数据将不会成为响应式,主要了为优化,对不需要响应式的数据减少proxy的递归成响应式
标记一个对象,使其永远不会转换为 proxy。返回对象本身。
vue3.x自定义Hooks
| 1 | //useGetMousePosition.js | 
| 1 | //Test.vue | 
vue3中的两种子传父
| 1 | //方法1 | 
自定义hooks
当有公共的逻辑时,将状态data与方法提出封闭在一个js文件中的函数里,导出data数据
| 1 | import { onBeforeUnmount, onMounted, onUnmounted, reactive } from 'vue'; | 
需要使用的地方 如test.vue
| 1 | import usePoint from '../hooks/index.js'; | 
其它变更
- 不再支持.native 
- 不再支持keycode的事件修饰符 如@click.13=’事件名’ 
- 全局注册组件放到了createApp中完成,详见: https://v3.cn.vuejs.org/guide/component-registration.html#%E5%85%A8%E5%B1%80%E6%B3%A8%E5%86%8C 
- 不再支持过滤器 vue.$filter语法 
- 新增 - <teleport>将组件挂载到某个dom- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- <teleport to="body"> 
 <div v-if="modalOpen" class="modal">
 <div>
 I'm a teleported modal!
 (My parent is "body")
 <button @click="modalOpen = false">
 Close
 </button>
 </div>
 </div>
 </teleport>
- 404 Not found 路由由 - path:*更改 详见:https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%93%8D%E5%BA%94%E8%B7%AF%E7%94%B1%E5%8F%82%E6%95%B0%E7%9A%84%E5%8F%98%E5%8C%96- 1 
 2
 3
 4
 5
 6- const routes = [ 
 // 将匹配所有内容并将其放在 `$route.params.pathMatch` 下
 { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
 // 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下
 { path: '/user-:afterUser(.*)', component: UserGeneric },
 ]
- app.config.globalProperties.foo = ‘bar 定义的数据/方法可以在Vue.2x(mounted/created)中找到全局定义的方法 - vue3获取全局数据/方法: - 重点:官网好像不推荐使用getCurrentInstance- getCurrentInstance只暴露给高阶使用场景,典型的比如在库中。强烈反对在应用的代码中使用- getCurrentInstance。请不要把它当作在组合式 API 中获取- this的替代方案来使用。- 详见: https://v3.cn.vuejs.org/api/composition-api.html#getcurrentinstance - 1 
 2
 3
 4
 5
 6
 7- //main.js 
 app.config.globalProperties.$vueName = 'Vue3全局挂载名称'
 //xxx.vue
 import {getCurrentInstance } from "vue";
 let {proxy} = getCurrentInstance()
 console.log(proxy.$vueName);
- Vue2.x中的beforeCreate的 - this指向的vue实例,到了Vue3中,setup/onMounted…生命周期的this指向的**- undefined**
- vue2.x中的生命周期包含beforeCreate可以获取vue3.x中的setup实例方法、数据,使用this.xxx - 1 
 2
 3
 4
 5
 6
 7
 8
 9- setup() { 
 const count = ref(0);
 return {
 count
 }
 }
 created(){
 console.log(this.count);//获取为0
 }
- vue3.x不再支持**.sync和emit(‘update:属性’,值)的语法** 
vue2与 vue3版本的双向数据绑定原理
vue2
| 1 | Object.defineProperty(obj,KEY,{ | 
vue2使用的object.defineProperty存在的问题
- 新增、删除一个属性时,视图不会更新 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32- <template> 
 <section>
 <h1>list.vue</h1>
 <h3 v-show="personInfo.name">用户名:{{ personInfo.name }}</h3>
 <h3 v-show="personInfo.age">年龄:{{ personInfo.age }}</h3>
 <h3 v-show="personInfo.school">学校:{{ personInfo.school }}</h3>
 <button @click="addSchool">添加一个学校</button>
 </section>
 </template>
 <script>
 import { defineComponent } from 'vue'
 export default defineComponent({
 setup() {
 
 },
 data(){
 return {
 personInfo:{
 name:'shao.yuhong',
 age:22
 }
 }
 },
 methods:{
 addSchool(){
 this.personInfo.addSchool = '重庆师范大学';
 console.log(this.personInfo);
 }
 }
 })
 </script>- 解决方案 - vue2.x提供了两种方法 - this.$set(this.personInfo,’school’,值) 
- Vue.set(this.personInfo,’school’,值) 
- this.$delete(this.personInfo,’school’,值) 
- Vue.delete(this.personInfo,’school’,值) 
 
vue3
vue3使用proxy代理,弥补了vue2上述问题,但是出现了使用watch监听一个Array/object时,newVal与oldVal相同的问题
proxy中get  set  deleteProerty
使用es6中的Reflect读取,设置、删除某个值,使用Reflect而不是直接返回是因为
好处是,通过Reflect返回值就会知道成功还是失败。
对于vue3而言,底层使用reflect会比较健壮,不容易出现有个错误就导致程序阻塞。如果使用object:
虽然可以通过try catch,但是底层源码如果各种try catch就会显得不优雅。
如果使用reflect,当出现错误的时候,进行逻辑判断从而代码继续往下走

vue.use()与Install
vue.use时,会找到对应的node_modules下的模块,这个模块存在一个文件名为index.js,并调用index.js中的install函数,在install函数中整合了所有组件,并导出
vue2 v-model自定义组件
平时我们使用 v-model 一般用在 input 标签上
| 1 | 1 <input v-model= 'content' ></input> | 
等价于
1
用在组件上类似于
| 1 | 1 Vue.component( 'base-input' , { | 
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
所以当我们把 v-model 用在自定义组件上时
| 1 | 1 父组件: | 
父组件使用 v-model 绑定在data中定义的属性 flag 传递给子组件(Child),子组件通过 props 接收,名为 value ,通过按钮触发对父组件中 flag 进行修改 ( $emit( ‘input’,!value ) )
通过在model属性中自定义事件:
如果遇到单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的,model 选项可以用来避免这样的冲突:
| 1 | 1 父组件: | 
通过使用 model 里的 event 方法自定义属性名,prop代表和props里的变量相对应
| 1 | <Child v-model="inputValue"></Child> | 
- 本文标题:vue3.x学习笔记
- 本文作者:邵预鸿
- 创建时间:2021-02-21 11:45:25
- 本文链接:/images/logo.jpg2021/02/21/vue3-x学习笔记/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
