鼎鼎知识库
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

在这里插入图片描述

初识

什么是Vue?

渐进式JavaScript 框架。渐进式就是指可以由浅入深的,由简单到困难的一种方式。

它的优点都有什么?

vue.js拥有更小的体积,压缩后的vue.js就只有33k;vue.js拥有更高的运行效率,vue.js是基于虚拟dom的,虚拟dom是一种可以预先通过JavaScript进行各种计算,把最终的dom操作计算出来并进行优化的技术。

因为这个Dom的操作属于预处理操作,并没有真实的操作Dom,所以叫做虚拟Dom。

vue.js基于虚拟Dom操作,大幅度提高了Dom的操作以及渲染效率。不仅如此,vue.js还实现了双向数据绑定。vue.js的双向数据绑定,让开发者不用再去操作Dom对象,可以把更多的精力投入到业务逻辑上。

vue3.0学习路线

  1. 先学习vue2.x,很多2.x内容依然保留;
  2. 先学习TypeScript,vue3.0是用TS重写的,想知其然知其所以然必须学习TS。

为什么学习vue3.0?

  • 性能比vue2.x快1.2~2倍
  • 按需编译,体积比vue2.x更小
  • 组合API
  • 更好的TS支持
  • 暴露了自定义渲染API
  • 更先进的组件

vue3.0是如何变快的?

1、diff方法优化

vue2.x中的虚拟dom是进行全量的对比。而vue3.0新增了静态标记。在与上次虚拟节点进行对比的时候,只对比带有patch flag的节点,并且可以通过flag的信息得知当前节点要对比的具体内容。

下面我们来举个例子,以下是代码片段。

<div>
  <p>标签</p>
  <p>{{msg}}</p>
</div>

vue2.x的diff算法是对虚拟dom树全量的对比。

在这里插入图片描述

vue3.0的diff算法在创建虚拟dom的时候,会根据dom中的内容是否发生变化,添加静态标记。只对比带有patch flag的节点。

在这里插入图片描述

我们可能看上面这个图不是很明白,那我们就用另一种方式直观看下。你们可以看到下图中存在数据绑定的元素中存在静态标记1,测试网址:

https://vue-next-template-explorer.netlify.app/

在这里插入图片描述

2、hoistStatic(静态提升)

vue2.x中无论元素是否参与更新,每次都会重新创建,然后再渲染。vue3.0中对于不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可。

我们再来去那个测试网站,在静态标记的选项前面打上对号,这时我们会发现不同,右边之前数据固定不变的标签,也就是这里的<p>标签</p>,被放在了render函数的外面。所以这样只会在全局创建一次,这样性能就明显提升了。

在这里插入图片描述

3、cacheHandlers(事件侦听器缓存)

默认情况下,如onClick事件会被视为动态绑定,所以每次都会追踪它的变化,但是因为是同一个函数,所以不用追踪变化,直接缓存起来复用即可。 好,我们来对比一下开启事件侦听器缓存前后。

  • 未开启事件侦听器缓存

我们会看到有一个静态标记,所以每次都会追踪。

在这里插入图片描述

  • 开启事件侦听器缓存

在事件侦听器缓存前打上对号,开启。我们看到没有了静态标记,就没有对比追踪了,性能就提升了。

在这里插入图片描述

实战

一、项目搭建

vite是尤大大开发的一款意图取代webpack的工具。其实现原理是利用ES6的import发送请求加载文件的特性。拦截这些请求,做一些编译,省去webpack冗长的打包时间。并将其与Rollup捆绑在一起用于生产。 在开发过程中没有捆绑。源代码中的ES Import语法直接提供给浏览器,浏览器通过本机<script module>支持对其进行解析,从而为每次导入发出HTTP请求。开发服务器拦截请求,并在必要时执行代码转换。例如,对*.vue文件的导入会在发送回浏览器之前即时进行编译。

1、全局安装vite脚手架

npm install -g create-vite-app

2、使用脚手架创建项目

create-vite-app projectName

3、进入项目文件夹

cd projectName

4、安装依赖

npm install

5、启动vue3.0项目

npm run dev

二、vue2.x存在的问题

2.x中的一点问题是当业务不断增多时,数据跟逻辑分散,会很难维护。

<template>
  <div>
    <div>
      <input type="text" v-model="obj.id">
      <input type="text" v-model="obj.con">
      <button @click="submit">提 交</button>
    </div>
    <ul>
      <li v-for="(item,index) in list" :key="item.id" @click="cli(index)">
        {{item.id}}-{{item.con}}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name:"filterBox",
  data(){
    return {
      list:[
        {
          id:1,
          con:"a"
        },
        {
          id:2,
          con:"b"
        }
      ],
      obj:{
        id:"",
        con:""
      }
      // 代码数据1
      // 代码数据2
      // ...
    }
  },
  methods:{
    cli(index){
      this.list = this.list.filter((item,idx)=>idx!==index);
      console.log(this.list);
    },
    submit(){
      // const obj = Object.assign({},this.obj);
      this.list.push(this.obj);
      this.obj.id = "";
      this.obj.con = "";
    },
    // 执行代码代码逻辑3
    // ...
  },
  computed:{
  	// 执行代码代码逻辑1
  },
  watch:{
   // 执行代码逻辑2
  }
}
</script>

<style>

</style>

三、组合API

ref

<template>
  <div>
    <p>{{count}}</p>
    <button @click="add">add</button>
  </div>
</template>

<script>
import {ref} from "vue"
export default {
  name: 'App',
  setup(){
    // 定义一个名称叫做count变量,这个变量的初始值是0
    // 这个变量发生该改变之后,vue会自动更新页面。
    const count  = ref(0);
	// 在组合API中,如果想定义方法,不用定义到methods中,直接在setup函数中定义即可。
    const add = () => {
      count.value+=1;
    }
	// 在组合API中定义的变量/方法,要想在外界使用,必须return出去。
    return {
      count,
      add
    }
  }
}
</script>

ref只能监听简单类型的变化,不能监听复杂类型的变化(对象/数组)。

另外,需要注意的是,如果是通过ref创建出来的数据,那么在template中使用的时候不用通过.value来获取。因为Vue会自动给我们添加.value

reactive

reactive 可以监听复杂类型的变化,如对象或者数组。

let state = reactive({
	name:"maomin"
});
// 或
let arr = reactive([1,2,3]);

我们来做一个小demo。

<template>
  <div>
    <ul>
      <li v-for="(item,index) in state.list" :key="item.id" @click="removeItem(index)">{{item.id}}--{{item.con}}</li>
    </ul>
  </div>
</template>

<script>
import {reactive} from "vue"
export default {
  name: 'App',
  setup(){
    const state  = reactive({
      list:[
        {
          id:1,
          con:"A"
        },
        {
          id:2,
          con:"B"
        },
        {
          id:3,
          con:"C"
        }
      ]
    });

    const removeItem = (index) => {
      state.list = state.list.filter((item,i)=>i!==index)
    }

    return {
      state,
      removeItem
    }
  }
}
</script>

我们可以改变下,把数据跟逻辑放在一块,这样就解决了vue2.x的数据跟逻辑分散的问题。

<template>
  <div>
    <ul>
      <li
        v-for="(item, index) in state.list"
        :key="item.id"
        @click="removeItem(index)"
      >
        {{ item.id }}--{{ item.con }}
      </li>
    </ul>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  name: "App",
  setup() {
    let {state,removeItem} = userReturn();
    return {
      state,
      removeItem,
    };
  },
};

function userReturn(params) {
  const state = reactive({
    list: [
      {
        id: 1,
        con: "A",
      },
      {
        id: 2,
        con: "B",
      },
      {
        id: 3,
        con: "C",
      },
    ],
  });

  const removeItem = (index) => {
    state.list = state.list.filter((item, i) => i !== index);
  };

  return {state,removeItem}
}
</script>

四、组合API本质

compositionAPIoptionAPI可以混合使用。其本质是注入。

<template>
  <div>
    <p>Vue2.x</p>
    <button @click="cli1">点击</button>
    <p>Vue3.0</p>
    <button @click="cli2">点击</button>
  </div>
</template>

<script>
import {ref} from "vue"
export default {
  name:"Demo2",
  data(){
    return {
      msg:"Vue2.x"
    }
  },
  methods:{
    cli1(){
      alert(this.msg);
    }
  },
  setup(){
    let txt = ref("Vue3.0"); // 注入到data函数内
    function cli2() { // 注入到methods属性内
      alert(txt.value); 
    }
    return {
      txt,
      cli2
    }
  }
}
</script>

<style>

</style>

五、setup执行时机与注意事项

setup函数,是在beforecreate钩子之前完成的。所以无法使用datamethods。 另外要注意的是setup是同步的,不是异步的。

<template>
  <div>
    <button @click="name">打开</button>
  </div>
</template>

<script>
export default {
  name:"Demo3",
  data(){
    return {
      msg:"hello"
    }
  },
  setup(){
    function name() {
      console.log(this.msg); // undefined
    }
    return {
      name
    }
  }
}
</script>

<style>

</style>

适合Vue3.0开发的UI框架

Ant Design of Vue

https://2x.antdv.com/docs/vue/introduce-cn/

Vant

https://vant-contrib.gitee.io/vant/next/#/zh-CN/