VUE3.X学习笔记

起步

创建项目

Vite(推荐使用)
  • Vite 是一款作者意图取代 webpack 的工具,目前仅为 vue3 提供服务,同样支持热更新
  • 其工作原理是利用 ES6import 会发送请求去加载文件的特性,拦截这些请求并做一些预编译,从而省去 webpack 冗长的打包时间
$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev
Vue-Cli(使用前请务必升级)
$ vue create <project name>
$ cd <project-name>
$ npm install
$ npm run dev
项目主要文件
index.html

index.html同样有一个id为app 元素用来挂载,通过 script 引入入口文件

在这里插入图片描述

App.vue

App.vue最大的不同点在于我们不再需要像2.X一样,在最外层再裹一层 div 作为模板根节点

在这里插入图片描述

main.js

main.js跟2.X有较大差异,3.X从 vue 引入 createApp 方法,再把 App 这个组件传入 createApp 方法 并进行挂载

在这里插入图片描述

模板指令

1.v-model
  1. prop和event的默认名称更改:value -> modelValue input -> update:modelValue

  2. 移除 v-bind 的 .sync 修饰符与组件的 model ,并替换为 v-model

  3. 3.x版本下的 v-model 可以在同一个组件上进行多个绑定

  4. 添加了创建自定义 v-model 修饰符的功能

2.X语法
<!-- parent -->
this.$emit('update:title', newValue);

<!-- children -->
<ChildComponent v-model="pageTitle" />

<!-- would be shorthand for: -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />

<!-- 可简化为.sync -->
<ChildComponent :title.sync="pageTitle" />
3.X语法
<!-- parent -->
this.$emit('update:title', newValue);

<!-- children -->
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />

<!-- would be shorthand for: -->
<ChildComponent
  :title="pageTitle"
  @update:title="pageTitle = $event"
  :content="pageContent"
  @update:content="pageContent = $event"
/>
迁移策略
<!-- 把代码中的.sync进行替换 -->	
<ChildComponent :title.sync="pageTitle" />

<!-- to be replaced with -->
<ChildComponent v-model:title="pageTitle" />
自定义修饰符
<!-- html -->
<div id="app">
  <my-component v-model.capitalize="myText"></my-component>
  {{ myText }}
</div>
// js
const app = Vue.createApp({
  data() {
    return {
      myText: ''
    }
  }
})

app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  methods: {
    emitValue(e) {
      let value = e.target.value
      if (this.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:modelValue', value)
    }
  },
  template: `<input
    type="text"
    :value="modelValue"
    @input="emitValue">`
})

app.mount('#app')

2.key属性(唯一标识:为了高效地更新虚拟DOM)
1.key 属性不再建议在 v-if v-else v-else-if 上使用,Vue3.x将会自动生成

2.X语法

<div v-if="condition" key="yes">Yes</div>
<div v-else key="no">No</div>

3.X语法

<div v-if="condition">Yes</div>
<div v-else>No</div>
2.如果主动添加 key 属性,必须要使用唯一值,不再允许使用 key 来强制分支重用

2.X语法

<div v-if="condition" key="a">Yes</div>
<div v-else key="a">No</div>

3.X语法

<!-- Vue 3.x (recommended solution: remove keys) -->
<div v-if="condition">Yes</div>
<div v-else>No</div>

<!-- Vue 3.x (alternate solution: make sure the keys are always unique) -->
<div v-if="condition" key="a">Yes</div>
<div v-else key="b">No</div>

3.<template v-for>key 应放在 <template>标签上(2.x放在子标签上)

2.X语法

<template v-for="item in list">
  <div :key="item.id">...</div>
  <span :key="item.id">...</span>
</template>

<template v-for="item in list">
  <div v-if="item.isVisible" :key="item.id">...</div>
  <span v-else :key="item.id">...</span>
</template>

3.X语法

<template v-for="item in list" :key="item.id">
  <div>...</div>
  <span>...</span>
</template>

<template v-for="item in list" :key="item.id">
  <div v-if="item.isVisible">...</div>
  <span v-else>...</span>
</template>
3.v-ifv-for 一同使用时优先级更改

在2.x中,v-ifv-for 一同使用时,v-for 的优先级大于 v-if ,3.x中,v-if 优先级将大于 v-for
迁移策略
由于语法上的歧义,避免在同一元素上使用它们

4.v-bind 现在对绑定顺序敏感
1.v-bind 的绑定顺序将影响渲染结果,在2.x语法中,vue假设开发人员希望单个属性始终覆盖定义的内容,在3.x语法中,开发人员将获得更多的控制权

2.X语法

<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="red"></div>

3.X语法

<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="blue"></div>

<!-- template -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- result -->
<div id="red"></div>

迁移策略
确保先定义v-bind属性,再定义各个属性

5.refv-for 一同使用时,将不再为 $refs 注册数组
1.在2.x中,当 v-for 用于元素或组件的时候, r e f s 的 引 用 信 息 为 包 含 D O M 节 点 或 组 件 实 例 的 数 组 , 即 : c o n s o l e . l o g ( t h i s . refs 的引用信息为包含DOM节点或组件实例的数组,即:console.log(this. refsDOM,console.log(this.refs)可以看到打印出来的是一个数组
2.在3.x中,$refs将不再自动创建数组,如果要从单个绑定中检索多个refs,需要把 ref 绑定到一个函数上以获得更大的灵活性
<div v-for="item in list" :ref="setItemRef"></div>

export default {
  data() {
    return {
      itemRefs: [] //不一定是数组,也可以是一个对象
    }
  },
  methods: {
    setItemRef(el) {
      this.itemRefs.push(el)
    }
  },
  beforeUpdate() {
    this.itemRefs = []
  },
  updated() {
    console.log(this.itemRefs)
  }
}

Composition API

2.X存在的问题

Vue3.X兼容2.X的写法,在2.X写法上,我们发现同一功能的业务逻辑非常分散,例如实现删除功能所需的数据放在 data 里,实现该功能的方法可能放在 methods 里,也有可能放在 computedwatch 里,在大项目中会造成后期维护困难,例如:

<script>
export default {
  name: 'App',
  data() {
    return {
      msg: '模块一',
      msg2: '模块二'
    }
  },
  methods: {
    add() { '模块一的方法' },
    remove() { '模块二的方法' }
  },
  computed: {
	'模块一',
    '模块二'
  },
  watch: {
	'模块一',
    '模块二'
  }
}
</script>

3.X解决方法

3.X为了解决代码碎片化的问题,引入了 Composition API,它能把同一功能的业务逻辑整合在一起,极大地提高了代码的可维护性,例如:

在这里插入图片描述

代码实现:

<!- App.vue ->
<template>
  <form action="">
    <input type="text" v-model="state2.list.id">
    <input type="text" v-model="state2.list.name">
    <input type="text" v-model="state2.list.age">
    <input type="submit" @click="add" value="新增">
  </form>
  <ul @click="operation" id="list">
    <li v-for="(item, index) in state.list" :key="index">
      <span style="margin-right: 10px">{{ item.name }}-{{ item.age }}</span>
      <button id="edit">修改</button>
      <button id="del">删除</button>
    </li>
  </ul>
</template>

<script>
import rowOperation from './rowOperation.js';
import addOperation from './addOperation.js';
export default {
  name: 'App2',
  setup() {
    let { state, operation } = rowOperation();
    let { state2, add } = addOperation(state);
    // 所有需要在视图中展示的数据和使用的方法都必须return出来
    return {state, operation, state2, add};
  }
}
</script>
// rowOperation.js 行操作
import {reactive} from 'vue';
function rowOperation() {
  let state = reactive({
    list: [
      {id: 0, name: 'zs', age: 15},
      {id: 1, name: 'ls', age: 18},
      {id: 2, name: 'ww', age: 19}
    ]
  })
  function operation(e) {
    e = e || window.event;
    let target = e.target || e.srcElement; //兼容IE8
    if(target.parentNode.tagName.toLowerCase() == 'li') {
      let li = document.querySelectorAll('li'); //querySelectorAll返回类数组
      let index = Array.prototype.indexOf.call(li, target.parentNode); 
      switch(target.id) {
        case 'edit':
          edit(index);
          break;
        case 'del':
          del(index);
      }
    }
  }
  // 编辑
  function edit(index) {
    ...
  }
  // 删除
  function del(index) {
    ...
  }
  // 记得把在视图展示的数据和用到的方法return出来
  return {state, operation};
}
export default rowOperation;
// addOperation.js 新增操作
import {reactive} from 'vue';
function addOperation(state) {
  let state2 = reactive({
    list: {
      id: '',
      name: '',
      age: ''
    }
  })
  function add(e) {
    e.preventDefault();
    ...
  }
  return {state2, add};
}
export default addOperation;

Composition API 的本质

Composition API 可以称为组合API,也可称之为注入API,它的本质是把 Composition API 暴露出来的数据和方法注入到 datamethods 中,例如:

import {ref} from 'vue';
export default {
    data() {
        return {
            msg1: '123'
            //msg2: 0
        }
    },
    methods: {
        myFun1() {
            ...
        }
        // myFun2() {
        //     ...
        // }
    },
    setup() {
        let msg2 = ref(0);
        function myFun2() {
            ...
        }
        return {state, myFun2};
    }
}

setup()的执行时间与注意点

Vue3.X 允许 Composition API 和 Option API 混合使用,但是 setup() 函数的执行时间是在 beforeCreate 之前,因此无法调用 data 和 methods ,vue3.X为了避免在 setup() 中误用 data 和 methods ,this 被设置为 undefined ,即:

export default {
    data() {
        return {
            msg: 'hello'
        }
    },
    methods: {
        myFun() {
            ...
        }
    },
    setup() {
        console.log(this); //undefined
        console.log(this.msg); //error
        this.myFun(); //error
    }
}

注意:setup() 不能是异步函数!!例:

async setup() { //页面内容将无法展示
    ....
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monster0936

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值