Vue3 学习笔记

167 阅读11分钟

1. computed的使用

  1. 作用
    1. 在模板中需要对数据进行复杂处理,且可能多次使用的情况下,使用计算属性可使数据结构更加清晰。
    2. 如果依赖数据没有发生变化,计算属性会从缓存中获取,不会重新计算。
    3. 模板里面的数据通过v-model绑定后,如果这个数据是通过计算属性得来的,那么访问的时候触发get,get()里面return什么,v-model就绑定什么。当这个数据被修改的时候,就会触发到set方法,修改的值就会当作参数,传给set。
      // 以下是computed实现全选/全不选的部分代码 
      <template>
           <span>全选:</span><input type="checkbox" v-model="allDone" />
      </template>
      <script setup lang="ts">
       import { ref, computed, watchEffect } from "vue";
       // isActive 是用来计算未完成的todoList的数量
       const isActive = computed(() => {
          return todoList.value.filter((item) => !item.done).length;
        });
       const allDone = computed({
        // 在get()里面, 
        get: () => {
          return isActive.value === 0;
        },
        // 在切换全选的时候 遍历todoList 把done字段改成和allDone一样即可
        set: (val) => {
          todoList.value.forEach((element) => {
            element.done = val;
          });
        },
      });
      </script>
      
  2. 优势
    1. 计算属性会基于他们的依赖关系进行缓存,当数据不发生变化时候,计算属性是不需要重新计算的。当依赖的数据发生变化,在使用时,计算属性依然会重新进行计算。
  3. vue3的computed
    1. computed 返回的是一个ref对象

2. methods

  1. 注意事项:
    1. 里面不可以使用箭头函数。因为箭头函数绑定了父级作用域的上下文(指向 window ),所以 this 不会指向组件实例。

3. 基本指令

  1. v-once 用于指定元素或者组件只渲染一次。当数据发生变化时。元素或者组件以及所有的子元素都将视为静态内容跳过。(可用于性能优化)
  2. v-text / v-html / v-pre
  3. v-cloak
  4. v-bind (绑定一个或者多个属性值,或者向另一个组件传递props值)
    1. 绑定class的两种方式
      1. 对象语法
        1. <div :class="{ 'active': isActive, nba: true }"></div>
        2. 也可以直接绑定一个对象 <div :class="classObj"></div>
      2. 数组语法
        1. <div :class="['active', nba]"></div>
    2. 绑定style的两种方式
      1. 对象语法
        1. div :style="{ fontSize: '12px', color: 'red' }"></div> 同样也可以绑定一个定义好的对象
        2. <div :style="[styleObj1, styleObj2]"></div> 这样可以将多个样式对象应用到元素上。
    3. 绑定属性名 :[name]="值"
    4. 绑定一个对象的所有属性 v-bind="obj" obj对象会被拆解成元素的各个属性。
  5. v-on (@)绑定事件
    1. 修饰符(对事件进行了一些特殊的处理)
      1. .stop 禁止冒泡 调用 event.stopPropagation()
      2. .prevent 禁止默认事件 调用 event.preventDefault()
        1. 示例 <form @submit.prevent></form>
      3. .capture 添加事件监听器时使用事件捕获模式,即内部元素触发的事件先在此处理,然后才交由内部元素进行处理。
      4. .self
      5. .{keyAlias} - 按键修饰符
      6. .once - 只触发一次回调
      7. .left - 只点击鼠标左键时触发
      8. .right - 只点击鼠标右键时触发
      9. .middle() - 只点击鼠标中键时触发
      10. .passive - {passive: true}模式添加侦听器
    2. 基本使用
      1. 可以给一个元素绑定多个事件 <div v-on="{ click: btnClick, mouseove: mouseMove }"></div>
    3. 参数传递
      1. 如果该方法不需要额外参数, 那么方法后的()可不添加
      2. 如果方法本身有一个参数,那么默认会将原生事件的event参数传递进去
      3. 如果需要同时传入某个参数, 同时需要event时,可以通过$event传入事件。 <div v-on="{ click: btnClick, mouseove: mouseMove }"></div>

4. slot (插槽)

  1. 具名插槽
    1. 即有名字的slot,若没有指定name属性的话, 会默认有 "default"。 <slot name="header></slot>
    2. 使用的时候,可以在template元素上使用 v-slot 指令,并以 v-slot 的参数形式提供其名称 <template v-slot:header></template>。template元素中的所有内容都将会被传入相应的插槽。简写可以写为 <template #header></template>
    3. v-slot 只能用于template上,除独占默认插槽以外。

5. 使用localStorage实现本地存储

  1. 相关Api
    1. localStorage.getItem(key) //获取指定key对应的值
    2. localStorage.setItem(key, value) //接收键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值
    3. localStorage.removeItem(key) //从存储中删除该键名
    4. localStorage.clear() // 清空存储中的所有数据
  2. 注意事项
    1. api里的键和值的类型均为字符串,我们一般存储的是JSON,但是localStorage会自动将其转换称字符串格式,所以可以使用JSON.stringify()来将JSON转换为字符串, 读取的时候要使用JSON.parse()将JSON字符串转换为JSON对象

6. scoped

  1. 作用
    1. 使样式私有化,即定义的CSS就只会应用到当前组件上的元素上。
  2. 原理
    1. 主要通过postcss转译实现。标签和样式的属性上都新增了 data-v 的前缀(唯一且不重复的动态属性),确保只在当前组件上生效
  3. 其它
    1. 如果想要在scoped内部写全局样式,可以使用 :global来标记
    2. 也可以使用 v-bind 函数, 直接在css中使用JavaScript中的变量

4.侦听响应式数据变化

4.1 watchEffect

  1. 使用
    1. 首先,watchEffect 传入的函数会立即执行一次, 并且在执行的过程中会收集依赖;其次只有在收集的依赖发生变化时,watchEffect()传入的函数才会再次执行。
  2. 停止侦听 - 调用stopWatch()就行
    const stopWatch = watchEffect(() => {});
    
  3. 清除副作用

4.2 watch

  1. 基本使用
    1. 当定义在data里的数据发生变化,且想要做一些逻辑上的处理的时候,可使用侦听器。
    2. 监听的是定义在data里的属性或者是props进行传值的内容
        // 需要监听的值,以及变化后的新值和变化前的旧值
        watch(value, (newValue, oldValue) => {}, {
          immediate: true,  // 立即执行侦听
          deep: true,  // 深度侦听
        });
    
    1. 默认情况下,侦听器只会针对监听的数据本身的改变(内部发生的改变时不能侦听),即如果侦听的是一个对象,watch是可以侦听到对象整体的变化的,但是不能侦听到对象的属性的变化。如果要侦听的话,需使用 deep: true。
  2. 注意事项
    1. watch需要侦听特定的数据源,并在回调函数中执行副作用
    2. 默认情况它是惰性的,只有当被侦听的源发生变化时才会执行回调

4.3 $watch API

  1. 用法同watch,但是其是有返回值的。通常在created生命周期里面使用

4.3 区别

  1. watchEffect 将在方法的任何依赖项发生更改时运行,watch 跟踪一个或多个特定的响应性属性,并且仅在该属性发生更改时运行。
  2. 默认情况下,watch 是惰性的,因此仅当依赖项更改时才会触发。watchEffect 在创建组件后立即运行,然后跟踪依赖关系。但是,我们可以为 watch 传递一个 immediate 属性,使其在初始化时运行。

5. v-model

  1. 基本使用
    1. 可以在表单 input、textarea以及select元素上创建双向数据绑定,他会根据控件类型自动选取正确的方法来更新元素。
    2. 负责监听用户的输入事件并更新数据
  2. 原理
    1. v-bind 绑定value属性的值
    2. v-on 绑定input事件监听到函数中,函数回获取最新的值赋值给绑定的属性中
     <input type="text" name="" id="" v-model="currentIndex" />
     // 等价于 
     // 默认情况下 v-model在进行双向绑定时,绑定的是input事件,即每次内容输入后就将最新的值和绑定的属性进行同步。
     <input
        type="text"
        :value="currentIndex"
        @input="currentIndex = $event.target.value"
      />
    
  3. 修饰符
    1. .lazy 将绑定的事件切换为change事件,只有在提交时(例如回车)才会触发
    2. .number 将v-model绑定的值转换为数字类型
    3. .trim 过滤输入的首尾空白字符
  4. 绑定checkbox
    1. 单个勾选框的时候为boolean值,此时input的value不影响v-model的值
    2. 多个复选框时,因为可以选中多个,所以对应的data是个数组,当选中某一个时,就会将input的value添加到数组中。

组件化开发

1. 注册组件

  1. 注册组件分为以下两种:
    1. 全局组件:在任何其他的组件中都可以使用的组件
    2. 局部组件:只有在注册的组件中才能使用的组件

1. 注册全局组件

  1. 全局组件需要使用我们全局创建的app来注册组件
  2. 通过 component方法传入组件的名称,组件对象(可以有自己的代码逻辑,比如有自己的data、computed、methods)即可注册一个全局组件
    1. 定义组件名称的方法有 kebab-case(短横线分隔符)、PascalCase(驼峰标识符 - 首字母大写)
    2. 如果使用短横线分隔符的话,引用组件也必须用短横向分隔符;而驼峰标识符的话,在引用组件的时候,两种命名法都可以引用。
  3. 之后可以在App组件的template直接使用这个全局组件
    createApp(App).use(router).mount("#app");
    App.component("MyComponent", {
      template: "",
        data() {
          return {};
        },
    });
    

2. 注册局部组件

  1. 局部注册是在我们需要使用到的组件中,通过components属性来注册,components选项对应的是一个对象,对象中的键值对是 组件名称:组件对象

2.组件之间的通信

1. 父子组件的通信

  1. 父组件传递给子组件:通过props属性
    1. props是定义在组件上的一些自定义属性,父组件给属性赋值,子组件通过属性的名称取到对应的值
    2. props传值的方式
      1. 字符串数组,数组中的字符串是自定义属性的名称 props: ['value']
      2. 对象类型,可以指定要传递的类型、是否必须及默认值等等。
        props: {
            title: String,
            value: {
              type: String,  // 类型
              defalut: 'hi', // 默认值
              required: true // 是否必须
            }
        }
        
      3. props传入的类型是一个对象或者数组的时候,这里的默认值必须是一个函数
  2. 子组件传递给父组件:通过$emit触发事件
  3. 具体步骤
    1. 在子组件中定义好事件,之后在父组件中以v-on的方式传入要监听的事件名称,并且绑定到对应的方法中,最后,在子组件触发事件,根据事件名称触发对应的事件。
      //  setup 语法
      // 在setup中必须使用 defineProps 和 defineEmits API来声明props和emits(无需引入)。
       const emit = defineEmits(["handleClick"]);
       function handleClick(index: number) {
         emit("handleClick", index);
       }
       // props 的用法 - 第一个参数传类型, 第二个参数传默认值
       const props = withDefaults(
         defineProps<{
           options: EChartsOption // echarts option的类型
           width?: string // ? 代表是可选类型
           height?: string // ? 代表是可选类型
         }>(),
         {
           width: '100%',
           height: '360px'
         }
       )
       
       // vue2/vue3的写法 - 可是个数组,也可以是个对象(可以对传递的参数进行验证)
       emits: ['handleClick']
       emits: {
           addOne: null,
           addTen: function (payload) {}
       }
      

2. 非prop的Attribute

  1. 定义 当我们传递给一个组件某个属性,但是该属性并没有定义对应的prop或者emits,就称之为非props的attribute。常见的包括class、style、id属性。

3. Provide和Inject - 用于非父子组件之间的通信

  1. 使用情景 比如有一些深度嵌套的组件,子组件想要获取父组件的部分内容。在这种情况下,如果使用props沿着组件链逐级

4. 全局事件总线mitt库

  1. Vue3从实例中移除了 onon、off、

Webpack相关知识

  1. 为什么要使用webpack
    随着项目越来越复杂,会采用组件化的方式来进行开发,即意味着每个组件都会有自己的模板、脚本逻辑、样式等。当然我们依然可以把它们抽离到单独的js、css文件中,但是他们还是会分离开来,也包括我们的script是在一个全局的作用域下,很容易出现命名冲突的问题,并且代码为了适配一些浏览器,必须使用es5的语法;所以在编写代码完成之后,依然需要通过工具对代码进行重新构建。所以在真实开发中,我们可通过 后缀名为 .value 的single-file components(单文件组件来解决),并且可以使用webpack或者vite或者rollup等构建工具来对其进行处理。

    1. 使用SFC(单文件的特点)
      1. 代码高亮
      2. es6、commonJS的模块化能力
      3. 组件作用域的css
      4. 可以使用预处理器来构建更加丰富的组件,比如 TypeScript、Babel、Less等
  2. webpack的默认打包

    1. 在目录下直接执行 webpack(使用的是全局 webpack),webpack会查找当前目录下的src/index.js作为入口,如果没有此文件,就会报错。当然也可以指定入口和出口。
      npx webpack --entry ./src/main.js --output-path ./build
    2. 会生成一个dist文件夹,里面存放一个main.js的文件(被压缩和丑化了),这就是我们打包之后的文件。
  3. 安装

    npm install webpack webpack-cli –g # 全局安装
    npm install webpack webpack-cli –D # 局部安装
    
  4. 创建局部的webpack

    1. 创建 package.json 文件,用来管理项目的信息,库依赖等 npm init
    2. 安装局部的webpack npm install webpack webpack-cli –D # 局部安装
    3. 使用局部的webpack npx webpack
    4. 在package.json中创建scripts脚本, 执行脚本打包即可
    "scripts": {
        "build": "webpack"
    }
    npm run build(打包命令)
    
    1. 通常可以在根目录下创建一个 webpack.config.js文件,来作为webpack的配置文件。
  5. loader

5. 动画

1. transition

  1. 命名规则
    1. 如果没有指定transition的name属性,那么所有的class都是以v-作为默认前缀,反之如果有name属性,那么所有的class都会以name的属性值开头。
  2. 第三方库推荐
    1. animate.css
      1. 安装 - npm install animate.css
      2. 在 main.js 引入 - import "animate.css"
      3. 直接使用animate库中定义的 keyframes 动画/直接使用animate库提供给我们的类;
    2. gasp库(使用JavaScript来实现一些动画的效果)
      1. 安装 - npm install gasp
  3. 列表过渡 - <transition-group>
    1. 默认情况下,其不会渲染一个元素的包裹器,但是可以通过指定tag属性渲染
    2. 内部元素需要指定唯一的key属性
    3. css过渡的类会被应用在内部的元素中,而不是这个组/容器本身
    4. 过渡模式不可用,因为我们不再相互切换特有的元素
  4. transition组件的JavaScript钩子

6. vuex

  1. 使用场景
    1. 我们是使用组件化机制来搭建项目的,每个组件内部有自己的数据和模板。但是总有些数据是需要共享的,如当前登录的用户名,权限等数据,如果都在组件内部传递,会变得非常混乱。所以vuex就是相当于项目中的大管家,集中式存储管理应用中的所有组件的状态。
  2. 核心属性
    1. state - 定义数据
    2. getter
    3. mutation - 同步的修改数据,并在组件中使用commit去调用mutations。
    4. actions - 异步修改数据,并在组件中使用store.dispatch调用action
    5. modules
  3. 其它
    1. vuex对TypeScript的支持不好,更推荐Pinia。

7. vue-router

  1. spa (single page application) 单页面应用程序
    1. 优势: 路由跳转不需要刷新页面
  2. 实现原理
    路由就是用来解析URL实现不同页面之间的跳转,目前是 hash 和 history两种方式
  3. 实现跳转的方式
    1. hash模式 (#)

      在页面进行跳转的时候,hash值的变化并不会导致页面的刷新,只是会触发hashchange事件,通过对hashchange时间的监听,我们就可以在fn函数内部进行动态的页面切换 window.addEventListener('hashchange',fn)
    2. history模式 2014年以后,因为HTML5标准发布,浏览器多了两个API: pushState和replaceState。通过这两个API,我们可以改变URL地址,并且浏览器不会向后端发送请求。

面试常问

  1. v-if 和 v-show的区别
  • 首先,v-show不支持template;
  • 其次,v-show元素是通过css的display属性来进行切换的,其dom实际上都是有渲染的。v-if为false的时候,其对应的元素根本不会被渲染到dom中。
  • 最后,元素需要在显示和隐藏之间频繁的切换就是用v-show,否则就使用v-if
  1. 定义methods里的方法时,不可以使用箭头函数
  • 如果使用箭头函数的话,this指向window(箭头函数不绑定this)。

vue3

MVVM模型

vue3 带来的变化

  1. 使用proxy进行数据劫持
  2. 删除了一些不必要的api
  3. 由Option API 到 composition API

webpack基础知识

webpack is a static module bundle for modern JavaScript application

基本指令

  1. 安装 npm install webpack webpack-cli -g (-g 全局安装 / -D 局部安装)

  2. 打包

    • 全局打包(不推荐) webpack
    • 局部打包
      1. cd到项目里,执行 npm init / npm init -y 创建 package.json文件
      2. 安装开发/生产依赖 npm install webpack webpack-cli --save-dev 等价于 npm install webpack webpack-cli -D(开发依赖) 会创建 package-lock.json 记录了安装的各个依赖的版本号 和 node_modules
      3. 打包
        // 方式一:找到node_modules 的 .bin目录下 的webpack文件 即输入 ./node_modules/.bin/webpack 等价于 npx webpack; 
       
        // 方式二:在package.json的scripts定义打包方式
        scripts: {
            build: "webpack"
        }
        //运行
        npm run build
    
  3. 指定打包的入口和出口

      // 方式一:使用指令 `npx webpack --entry ./src/main.js --output-path ./build` 
      // 方式二:新建 webpack.config.js 使用commonJS指定 entry 和 output  
    

loader的使用 - 可以用来对模块的源代码进行转换

  • style-loader 在html页面创建style标签,再把对应的css样式插入到页面上
  • css-loader 将.css文件进行解析
    1. 安装指令:npm install css-loader -D
    2. 使用loader加载css文件
      1. 方式一:内联方式(非常少用),在引入css文件的时候 import "css-loader!../css/style.css !表分割 用css-loader加载style.css
      2. 方式二:在webpack.config.js的导出对象上新增module属性 module属性里面有rules数组,数组里面是一个一个的对象
          module.exports = {
            module: {
              rules: [
                {
                  test: /\.css$/   //正则表达式(.需要转义 即加上\ $表示以什么结尾) 表示以.css结尾的,就使用这个rule
                  // 1. loader的写法(语法糖) 
                  // loader: "css-loader", // 表示以.css结尾的 就使用这个loader
                  // 2. 完整写法
                  use: [
                    // 从右往左先读
                    "style-loader"
                    "css-loader"
                    // 也可以传参 等价于
                    {
                      loader: "css-loader",
                      options: {}
                    }
                  ]
                }
              ]
              }
          }
      
  • less-loader
    1. 安装指令
      1. npm install less-loader -D (安装less-loader)
      2. npm install less -D (安装less)
    2. 配置webpack.config.js
      {
        test: /\.less$/,
        use: [
          "style-loader"
          "css-loader"
          "less-loader"
        ]
      }
      
  • postcss 工具 - 通过JavaScript来转换样式的工具 其可以帮助我们进行一些css的转换和适配 比如自动添加浏览器前缀 css样式的重置
    1. 安装指令 npm install postcss postcss-cli -D
    2. 需要给浏览器添加前缀,所以需要安装 autoprefixer npm install autoprefixer -D
    3. 直接使用使用postcss工具,并且指定使用autoprefixer npx postcss --use autoprefixer -o end.css ./src/css/style.css (-o 输出 即将style.css输出为end.css)
    4. 也可以使用 postcss-preset-env 这个插件的功能会比 autoprefixer 强大