前端知识点总结——Vuex / 事件循环 / 宏任务和微任务 / Vue3和Vue2的区别以及双向绑定的区别 / Vue的特性 / js垃圾回收机制 / less、sass

Vuex

作用:全局状态管理。在state中定义一个数据后,可以在所在项目中的任何一个组件里进行获取、修改,并且修改的结果可以得到全局的响应变更。

Vuex的核心部分:State,Getter,Mutation,Action

  1. state:包含了store中存储的各个状态。
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  }
 })
  1. getter: 类似于 Vue 中的计算属性,根据其他 getter 或 state 计算返回值。
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})
  1. mutation: 包含有一组方法,是改变store中状态的执行者,只能是同步操作。
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

//通过store.commit方法调用
store.commit('increment')

载荷(Payload)

mutations: {
  increment (state, n) {
    state.count += n
  }
}

//第一个参数是state,后面的参数是向 store.commit 传入的额外的参数
this.$store.commit('increment', 10)

// 以载荷形式
store.commit('increment'{
  amount: 10   //这是额外的参数
})

// 或者使用对象风格的提交方式
store.commit({
  type: 'increment',
  amount: 10   //这是额外的参数
})
  1. action: 包含有一组方法,其中可以包含异步操作。
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

//使用参数解构来简化代码
actions: {
  increment ({ commit }) {
    commit('increment')
  }
}
  • action进行异步调用:
actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

//调用方式
store.dispatch('actionA').then(() => {
	……
})

//配合async/await使用,假设 getData() 和 getOtherData() 返回的是 Promise
actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}
  1. modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

Vuex的运行逻辑
在这里插入图片描述
Vue组件使用this.$store.dispatch调用ActionAction使用this.$store.commit调用MutationsMutations修改State的数据,再使用Render函数重新渲染。

  • Backend API:建议与后端交互放在Actions进行操作
  • Devtools:Vue官方为我们提供的Vuex状态调试工具, 它能跟踪到Vuex的每一个操作和状态改变

Mutations是否可以省略?
可以省略,省略后可以直接使用Actions操作State数据,但是不建议。省略后会出现几个问题:

  1. Devtools工具无法监控到对State数据的操作
  2. Actions可以对Mutations进行分层和重复调用

事件循环(Event Loop)

JavaScript特点就是单线程

为了利用CPU多核计算的能力,HTML5提出了Web Worker标准,允许JavaScript创建多个线程,但是子线程完全受主线程控制且不能操作DOM

异步任务

为了避免一些操作较慢的设备(Ajax操作)影响主线程的执行,提出了异步任务。可以将等待中的人任务挂起,等待IO设备操作完成后再调用该任务继续执行。

  • 同步任务:在主线程上排队执行的任务,前一个任务执行完毕才能执行后一个任务
  • 异步任务:不进入主线程,进入“任务队列”(task queue),当“任务队列”通知主线程某个异步任务可以执行后,该异步任务才能进入主线程执行。

主要主线程空了,就会去读取“任务队列”

回调函数(callback)

  • 回调函数是被主线程挂起的代码。异步任务必须指定回调函数,主线程执行异步任务就是执行回调函数。
  • “任务队列”中的事件,除了设备IO以外还包括了一些用户产生的事件(鼠标点击,页面滚动)。只要指定了回调函数的事件都会加入到“任务队列”中,等待主线程读取
  • “任务队列”是一个先进先出的数据结构,排在前面的事件优先被主线程读取执行。只要执行栈清空,“任务队列”的第一个事件就会进入主线程。但是,由于存在“定时器”功能,主线程要检查一下执行时间,到了规定时间才能进入主线程。

事件循环

在这里插入图片描述

  • 主线程运行时生成堆和栈
  • 栈中的代码调用外部API
  • 外部API在“任务队列”中加入各种事件
  • 主线程执行完毕后读取“任务队列”,依次执行回调函数
  • 同步任务总是先于异步任务执行

定时器

"任务队列"还可以放置定时事件,即指定某些代码在多少时间之后执行。

console.log(1);
setTimeout(function(){console.log(2);},0);
console.log(3);
// 1 3 2

setTimeout(fn,0)的含义是在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。

宏任务和微任务

  • 宏任务:由宿主(浏览器、Node)发起,后于微任务运行,会触发新一轮的事件循环
    • setTimeout
    • setInterval
    • I/O
    • setImmediate(Node.js)
    • requestAnimationFrame(浏览器)
  • 微任务:由JS引擎发起,先于宏任务运行,不会触发新一轮的事件循环
    • Promise
    • MutationObserver(浏览器)
    • process.nextTick(Node.js)

Vue3和Vue2的区别以及双向绑定的区别

Vue3和Vue2的区别

  1. 获取变量的区别

Vue2

<template>
  <div class='form-element'>
    <h2> {{ title }} </h2>
    <input type='text' v-model='username' placeholder='Username' />
    
    <input type='password' v-model='password' placeholder='Password' />

    <button @click='login'>
      Submit
    </button>
    <p> 
      Values: {{ username + ' ' + password }}
    </p>
  </div>
</template>

Vue3

<template>
  <div class='form-element'>
    <h2> {{ state.title }} </h2>
    <input
    	type='text'
    	v-model='state.username'
    	placeholder='Username'
    />
    
    <input
    	type='password'
    	v-model='state.password'
    	placeholder='Password'
    />

    <button @click='login'>
      Submit
    </button>
    <p> 
      Values: {{ state.username + ' ' + state.password }}
    </p>
  </div>
</template>

Vue3中的反应数据(Reactive Data)是包含在一个反应状态(Reactive State)变量中。所以我们需要访问这个反应状态来获取数据值state.username

  1. 建立数据data的区别

Vue2

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  }
}

Vue3

import { reactive } from 'vue'

export default {
  props: {
    title: String
  },
  setup () {
    const state = reactive({
      username: '',
      password: ''
    })

    return { state }
  }
}

在Vue3,我们就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
使用以下三步来建立反应性数据:

  • 从vue引入reactive
  • 使用reactive()方法来声名我们的数据为反应性数据
  • 使用setup()方法来返回我们的反应性数据,从而我们的template可以获取这些反应性数据
  1. 编写methods的区别

Vue2

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    login () {
      // 登陆方法
    }
  }
}

Vue3

export default {
  props: {
    title: String
  },
  setup () {
    const state = reactive({
      username: '',
      password: ''
    })

    const login = () => {
      // 登陆方法
    }
    return { 
      login,
      state
    }
  }
}

Vue3 的合成型API里面的setup()方法也是可以用来操控methods的。创建声名方法其实和声名数据状态是一样的。— 我们需要先声名一个方法然后在setup()方法中返回return, 这样我们的组件内就可以调用这个方法了。

  1. 生命周期函数:mounted()为例

Vue2

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  },
  mounted () {
    console.log('组件已挂载')
  },
  methods: {
    login () {
      // login method
    }
  }
}

Vue3

import { reactive, onMounted } from 'vue'

export default {
  props: {
    title: String
  },
  setup () {
    // ..

    onMounted(() => {
      console.log('组件已挂载')
    })

    // ...
  }
}

需要另外从vue中引入。和刚刚引入reactive()一样,生命周期的挂载钩子叫onMounted()

  1. 计算属性

Vue2

export default {
  // .. 
  computed: {
    lowerCaseUsername () {
      return this.username.toLowerCase()
    }
  }
}

Vue3

import { reactive, onMounted, computed } from 'vue'

export default {
  props: {
    title: String
  },
  setup () {
    const state = reactive({
      username: '',
      password: '',
      lowerCaseUsername: computed(() => state.username.toLowerCase())
    })

    // ...
  }

在 Vue3 使用计算属性,我们先需要在组件内引入computed()
使用方式就和反应性数据reactive data一样,在state中加入一个计算属性

  1. Props的接收

Vue2

mounted () {
    console.log('title: ' + this.title)
}

Vue3

setup (props) {
    // ...

    onMounted(() => {
      console.log('title: ' + props.title)
    })

    // ...
}
  • 组件之间props参数传递是Vue2和Vue3的最大区别:this在Vue2和Vue3中代表的意义不同
    • Vue2的this代表当前组件,不是特定属性
    • Vue3的this不能拿到propsemitevents和组件内其他属性,可以通过setup()接收两个参数:propscontent(emit、slots、attrs)
  1. emit事件

Vue2

login () {
      this.$emit('login', {
        username: this.username,
        password: this.password
      })
 }

Vue3

setup (props, { emit }) { // 解构赋值
    // ...

    const login = () => {
      emit('login', {
        username: state.username,
        password: state.password
      })
    }

    // ...
}

setup()中的第二个参数content对象中就有emit,这个是和this.$emit是一样的。那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup()中随意使用了。

Vue2和Vue3在代码上的不同主要体现在:

  • 获取变量的区别
  • 建立数据data的区别
  • 编写methods的区别
  • 生命周期函数的区别
  • 计算属性的区别
  • Props的区别
  • emit的区别

Vue3和Vue2双向绑定的区别

Vue2

  • 使用Object.defineProperty进行数据劫持
  • vue需要递归遍历对象的所有属性挨个进行绑定
  • 数组的更新不能被检测到

Vue3

  • 使用Proxy进行数据劫持
  • 可以直接拦截整个对象,不需要再进行递归

Vue的特性

  • 双向数据绑定
  • 生命周期
  • 组件化
  • 客户端路由
  • 渐进式框架(路由、vuex、网络请求)

js垃圾回收机制

采用“标记-清除”算法

  • 垃圾回收器获取根并“标记”(记住)它们
  • 然后它访问并“标记”所有来自它们的引用
  • 然后它访问标记的对象并标记它们的引用。所有被访问的对象都被记住,以便以后不再访问同一个对象两次
  • 以此类推,直到有未访问的引用(可以从根访问)为止
  • 除标记的对象外,所有对象都被删除

less、sass

less

Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充。

  • less中的变量
    @变量名:变量值
  • 混合
    相当scss的混合宏
    ①无参数混合;实际上就是一个普通的class选择器,会被编译到css文件中.class{}
    ②有参无默认值混合声明:.class(@param){}调用:.class(paramValue);
    ③有参有默认值混合:声明:.class(@param:10px){}调用:.class(paramValue); 或 .class()
  • 匹配、@argument、嵌套

sass

Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能。

  • scss中的变量
    声明变量:$变量名:变量值,允许将变量嵌套在字符串中,但是变量必须使用 ${} 包裹
  • scss中的运算
    scss中的运算,会将单位进行运算,使用时需注意最终的单位是否正确
  • scss中的嵌套
    选择器嵌套 属性嵌套 伪类嵌
    ① 选择器嵌套 ul{li{}},嵌套默认表示后代选择器,如果需要子代选择器,可以在选择器前加>;可以在选择器的{}中,使用&表示上一层的选择器。
    ② 伪类嵌套: li{&:hover{}},在选择器的{}中,使用&配合伪类事件,可以表示当前选择器的伪类。
    ③ 属性嵌套: font:{size:18px;},对于属性名有-分割为多段的属性,可以使用属性嵌套,属性名的前半部分必须紧跟一个:才能用{}包裹属性的后半部分。
  • 混合宏
    使用@mixin声明混合宏,在其他选择器中使用@include调用混合宏
  • 继承
    声明一个普通class,在其他选择器中使用@extend继承这个class
  • 条件语句、循环、函数
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值