vue/vue3知识点总结

1、在.vue文件中style标签可以有两个属性<style  module>和<style scoped>

第一种:

<style>中使用scoped属性后,样式只作用在当前作用域,在less中不起作用。

第二种:

<style>中使用module属性, 可以形成名为$style的计算属性,从而在节点中动态绑定样式。

<style module>
    .test{color:red;}
</style>

使用1:
<span :class="$style.test"></span>

使用2:
<span :class="{[$style.test]:isRed}"></span>
注:isRed是在data中定义的boolean变量

可以在js中通过console.log(this.$style.red)进行访问

2、标签使用

- v-once :如果不想改变标签的内容,可以通过使用该指令执行一次性地插值,当数据改变时,插值处的内容不会更新。

- v-html:用于输出 html 代码

- v-bind :属性值(v-bind:id/v-bind:class)。对于布尔属性,常规值为 true 或 false,如果属性值为 null 或 undefined,则该属性不会显示出来。

3、事件修饰符

- stop:阻止冒泡
- prevent:阻止默认事件
- capture:阻止捕获
- self:只监听触发该元素的事件
- once:只触发一次
- left:左键事件
- right:右键事件
- middle:中间滚轮事件

示例:
<!-- 阻止单击事件冒泡 -->
<span @click.stop="doThis">测试事件</span>

<!-- 提交事件不再重载页面 -->
<form @submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联  -->
<a @click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form @submit.prevent></form>

<!-- 添加事件侦听器时使用事件捕获模式 -->
<div @click.capture="doThis">...</div>

<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div @click.self="doThat">...</div>

<!-- click 事件只能点击一次,2.1.4版本新增 -->
<a @click.once="doThis"></a>

4、按键修饰符

按键:
- enter
- tab
- delete (捕获 "删除" 和 "退格" 键)
- esc
- space
- up
- down
- left
- right

系统修饰符:
- ctrl
- alt
- shift
- meta

鼠标按钮修饰符:
- left
- right
- middle


举例:
<!-- 只有在 keyCode 是 13 时调用 this.submit() -->
<input @keyup.13="submit">
或:
<input @keyup.enter="submit">


<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>


<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

5、表单

(1)v-model

v-model 会根据控件类型自动选取正确的方法来更新元素。

v-model 会忽略所有表单元素的 value、checked、selected 属性的初始值,使用的是 data 选项中声明初始值。

v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

- text 和 textarea 元素使用 value 属性和 input 事件;

- checkbox 和 radio 使用 checked 属性和 change 事件;

- select 字段将 value 作为属性并将 change 作为事件。

但是有时我们可能想把值绑定到当前活动实例的一个动态属性上,这时可以用 v-bind 实现,此外,使用 v-bind 可以将输入值绑定到非字符串。

复选框 (Checkbox):
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
// 选中时
this.toggle === 'yes'
// 取消选中 
this.toggle === 'no'

单选框 (Radio):
<input type="radio" v-model="pick" v-bind:value="a" />
// 当选中时
this.pick === this.a


选择框选项 (Select):
<select v-model="selected">
  <!-- 内联对象字面量 -->
  <option :value="{ number: 123 }">123</option>
</select>
// 当被选中时
typeof this.selected // => 'object'
this.selected.number // => 123

修饰符:

- .lazy:在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

- .number:自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值)
<input v-model.number="age" type="number">

- .trim:自动过滤用户输入的首尾空格
<input v-model.trim="msg">

 6、vue兄弟组件之间通信

 有两个组件A和B,怎么实现A和B之间的通信呢?

需要借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发。

var bus = new Vue();

bus.$emit();
bus.$on();

定义A组件:

Vue.component("com-a",{
    template:`
        <div>
            <h1>我是A组件</h1>
            <input type="text" v-model="v"/>
            <button @click="sendTo">Click Me</button>
        </div>
    `,
    data:function(){
        return {
            v:""
        }
    },
    
    watch:{
        v:function(n){
            bus.$emit("msgTo",n)
        }
    },
    methods:{
        sendTo:function(){
            var me = this;
            bus.$emit("msgTo",me.v);
            me.v= "";
        }
    }
})

定义组件B:

Vue.component("com-b",{
    data:function(){
        return{
            name:[]
        }
    },
    template:`
        <div>
            <h1>我是B组件</h1>
            <p v-for="it,index in name">{{it}}</p>
        </div>
    `,
    mounted:function(){
        var me = this;
        bus.$on("msgTo",function(msg){
                me.name.push(msg);
        })
    }
})

使用:

<com-a></com-a>
<hr>
<com-b></com-b>

这样就可以完成组件之间的通信啦

7.vue动画 -- transition

8、vue项目本地启动后,使用localhost可以访问,但换成本地ip不能访问的情况。找到webpack.dev.js文件,将host:"localhost"改为host:"0.0.0.0"即可使用ip进行访问。




Vue3.0

从2.0基于对象的编程(OOP)转向了函数时编程(FP).

OOP特点是对象或class是对数据和逻辑的封装。在3里面,把相关的数据和操作写在了setup里面。FP特点是函数只做一件事返回一个值。

// 可将vue组件看作一个函数
<template>
    <div>测试</div>
</template>
<script>
    export default{
        props:{
            xxx:{
                type:XXX,
                default:""
            }
        }
    }
</script>

纯函数VS非纯函数对比:

纯函数特点:相同的输入产生相同的输出;不能有语义上可观察的函数"副作用"(side effect)。

在vue组件种,它需要获取数据、改变状态、修改DOM、事件监听等,这些可以理解为函数的“副作用”(side effect)。


响应式原理

vue2.0 是利用 Object.defineProperty可以挟持并自定义对象的 setter 操作和 getter 操作来实现的,但是这有一些问题:

  • 数组 这一数据类型的数据 defineProperty 无法直接挟持,需要使用比较 hack 的操作去完成
  •  操作在一些场景下无法捕获到,在无法挟持到的场景下,我们就必须使用 $set$delete 这些 Vue 封装的函数去代替 js 原生的值操作,增加了心智成本
  • 性能的浪费,因为无法知道具体哪些值是需要响应式的,2.0 对只要是在 data 里能挟持的都会挟持一边,但实际上开发者数据更改的粒度往往不会这么细,所以这会导致一定程度上的性能浪费(用 Object.freeze() 等操作可以在一定程度上解决这个问题)

vue3.0 则是使用 Proxy 来实现数据更改的监听,Proxy 从定义上来说简直就是完美的为 **数据挟持 **这一目的而准备的

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

从某种意义上来讲,Proxy 可以视为 Object.defineProperty 的强化,它拥有更丰富的可以挟持的内容,并且解决了上面描述使用 defineProperty 存在的问题:

  • 不再需要专门为 数组 进行特殊的挟持操作,Proxy 直接搞定
  •  操作 Proxy 也能直接挟持
  • 因为 Proxy 的一些特点,Proxy 可以实现惰性的挟持,而不需要深度的挟持所有值
  • 同时因为 Proxy 并不是对数据源进行更改,从而可以保证不会出现太多的副作用

依赖收集的区别:

2 中是通过 ObserverDepWatcher 这三个类来实现依赖收集;3 中是通过 track 收集依赖,通过 trigger 触发更新,本质上就是用 WeakMap,Map,Set 来实现


setup函数

// setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之间的函数
// setup函数中不能使用this
// setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新
// setup 若使用解构prop,可以通过使用 setup 函数中的 toRefs 来完成此操作
// context:attrs、slots、emit




import { toRefs } from 'vue'
....
setup(porps, context){
    // Attribute (非响应式对象)
    console.log(context.attrs)

     // 插槽 (非响应式对象)
    console.log(context.slots)

    // 触发事件 (方法)
    console.log(context.emit)    

    const { title } = toRefs(props);
    console.log(title.value)
}
....

在vue3种提供watchEffect的钩子函数:

import { onMounted,reactive,watchEffect } from "vue";
export default{
    name:"xxx",
    setup(props){
        onMounted(() => {......});
        wacthEffect() => {......});
        return{ ...... };
    },
    data(){return{.......}},
    wacth:{......},
    created(){......},
    mounted(){......}
}
  • watchEffect()函数:监听函数,在props中数据第一次初始化和更改时进行触发。这个方法在初始化时会在onMounted周期之前调用一次,但是此时dom节点未挂载,若进行操作dom会报错。

    // 第一个参数effect函数,effect()中还能接收一个参数onInvalidate()清除副作用函数,主要作用就是在组件销毁是进行 effect()的清除操作。
    
    
    import {ref,watchEffect} from "vue";
    export default {
        setup(){
            const count = ref(0);
            const effect = () => console.log(count.value);
            watchEffect(effect);
            setTimeout(() => count.value++,1000);
            return{ count };
        }
    }
    带参数:
    watchEffect((onInvalidate) => {
        onInvalidate(() => {
            // run if id has changed or watcher is stopped
        });
    });
    
    // 第二个参数options,类型是WatchEffectOptions,是指何时运行副作用函数。比如,你希望副作用函数在组件更新前发生,可以将 flush 设为 'pre'(默认是 'post')。还有 WatchEffectOptions 也可以用于 debug:onTrack 和 onTrigger 选项可用于调试一个侦听器的行为(当然只开发阶段有效)。
    watchEffect(
      () => {
        /* ... */
      },
      {
        flush: "pre",
        onTrigger(e) {
          debugger;
        },
      }
    );
    

  • template模板部分:通过Fragment()函数巧妙进行切片处理,在template中可以进行多个根节点的书写


核心方法

reactive

// 接收一个参数,判断这个参数是否是对象;
// 创建拦截器对象 handler,设置 get / set / deleteProperty
// 返回 Proxy 对象
// 返回的对象,重新赋值丢失响应式
// 返回的对象不可以解构

export function reactive(target) {
  const handler = {
    get(target, key, receiver) {
    },
    set(target, key, value, receiver) {
    },
    deleteProperty(target, key, receiver) {
    }
  }
 
  return new Proxy(target, handler) // targe 目标对象,handler
}
ref 

// 适用于基本数据类型的响应式对象转化
// 返回的对象,重新赋值成对象是响应式的

export function ref(raw) {
  // 判断 raw 是否是ref 创建的对象,如果是的话直接返回
  if (isObject(raw) && raw.__v_isRef) {
    return
  }
  let value = convert(raw) // 将 raw 转化为响应式对象,包括对象的对象
  const r = {
    __v_isRef: true, // ref 的标识
    get value() {
      return value
    },
    set value(newValue) {
      if (newValue !== value) {
        raw = newValue
        value = convert(raw)  // 将 newValue 转化为响应式对象,包括对象的对象
      }
    }
  }
  return r
}
toRefs

// 将 引用数据类型,遍历到 目标对象上,可实现解构方法,因 reactive 无法实现解构,可通过此方法进行解决

export function toRefs(proxy) {
  const ret = proxy instanceof Array ? new Array(proxy.length) : {}
 
  for (const key in proxy) {
    ret[key] = toProxyRef(proxy, key) // 将目标对象的值分别挂载到最外层,可实现属性-解构
  }
 
  return ret
}
 
function toProxyRef(proxy, key) {
  const r = {
    __v_isRef: true,
    get value() {
      return proxy[key]
    },
    set value(newValue) {
      proxy[key] = newValue
    }
  }
  return r
}
// mapGetters:vue中的计算属性
// mapState:变量 ,相当于this.$store.state.xxx
// mapMutations:vue中的methods

...
computed:{
            ...mapGetters('cart',{
            // 对应store中的this.$store.getters["cart/count"]
           count:'count' 
        }),
...mapState('user',[
            // 将this.user映射成this.$store.state.user.user
            'user'
        ]),
    },
methods:{
        ...mapMutations('user',[
            // 将this.delete映射为this.$store.commit('user/delete')
            'delete'
        ]),
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值