vue笔记

不定时更新说明

本文记录自己部分所学,将会不定时更新,对待技术,俺是认真的



Vue: 给 src 文件夹配置别名,通常用“@”

在 jsconfig.json 文件中添加如下代码:

{
	"ocmpilerOptions": {
		"baseUrl": "./",
		"paths": {
			"@/*": ["src/*"]
		}
	},
	"exclude": ["node_modules", "dist"]
}


Vue:v-on(@)事件修饰符

.native		// 主要是给自定义组件(标签上)添加原生事件
.top		// 阻止冒泡事件
.prevent	// 阻止默认事件
.once		// 监听事件只执行一次
@keydown	// 任意的键盘键按下
@keyup		// 任意键盘键抬起
@keyup.enter	// enter键抬起
@keydown.b		// b键按下


Vue: 异步编程的一种解决方案 Promise

3种状态:
Pending:进行中
Resolved:已完成
Rejected:失败
开始创建都是pending,只要执行相应的resolve或者reject都要相应改变状态,状态改完后是改不回来的
链式调用以及语法糖

var oPromise=new Promise(function(resolve,reject){
	resolve(1);
})
oPromise.then(function(value){
	console.log(value); //1
	return value*2;//return new Promise(function(resolve,reject){ resolve(value*2)}
}).then(function(value){
	console.log(value); //2
}).then(function(value){
	console.log(value); //undefined
	//return Promise.resolve('resolve') //return new Promise(function(resolve,reject){ resolve('resolve')}
    return 'resolve'
}).then(function(value){
	console.log(value); //resolve
	return Promise.reject('reject') //return new Promise(function(resolve,reject){ reject('reject')}
}).then(function(value){
	console.log(value)
},function(err){
	console.log(err) //reject
})

all 和 race
all:全部执行完成才停止
race:有一个执行完成就停止

//all(全部执行完成才停止)
function task(delay) {
    return new Promise(function (resolve) {
        setTimeout(function () {
            resolve(delay);
        }, delay);
    });
}
var startDate = Date.now();
// 所有promise变为resolve后程序退出
Promise.all([ //里面的是一个个promise的任务
    task(1), //这个任务是1秒钟后变为resolve状态
    task(32), //这是32
    task(64),
    task(128)
]).then(function (values) {
    console.log(Date.now() - startDate + 'ms');
    // >= 128ms
    console.log(values);    // [1,32,64,128]
});
 
-------------------------------------------------
//race(只要有一个执行完就停止)
function task(delay) {
    return new Promise(function (resolve) {
        setTimeout(function () {
            resolve(delay);
        }, delay);
    });
}
// 任何一个promise变为resolve或reject 的话程序就停止运行
Promise.race([
    task(1),
    task(32),
    task(64),
    task(128)
]).then(function (value) {
    console.log(value);  //1
});


Vue: 路由懒加载

解决白屏问题,优化用户体验

const HelloWorld = () => import('@/components/HelloWorld.vue')
export default new Router({
	routers:[
		{
			path: '/',
			name: 'HelloWorld',
			component: HelloWorld
		}
	]
})


Vue2:获取元素距浏览器上边框和左边框的位置

	
	const element = document.getElementById('...')
	let posTop = getElementTop(element)
	let posLeft = getElementLeft(element)
	let position = getElementPosition(element)

	// 计算盒子离浏览器上边框的距离
    getElementTop (element) {
      let actualTop = element.offsetTop
      let current = element.offsetParent
      while (current !== null) {
        actualTop += current.offsetTop
        current = current.offsetParent
      }
      return actualTop
    },
    // 计算盒子离浏览器左边框的距离
    getElementLeft (element) {
      let actualLeft = element.offsetLeft
      let current = element.offsetParent
      while (current !== null) {
        actualLeft += current.offsetLeft
        current = current.offsetParent
      }
      return actualLeft
    },
    // 合在一起
    getElementPosition (element) {
      let actualTop = element.offsetTop
      let actualLeft = element.offsetLeft
      let current = element.offsetParent
      while (current !== null) {
      	actualTop += current.offsetTop
        actualLeft += current.offsetLeft
        current = current.offsetParent
      }
      let elementPosition = {
		top: actualTop,
		left: actualLeft
	  }
      return elementPosition
    },


Vue2:ctrl+s/z/y 保存/上一步/下一步

1. 在 mouted 中设置监听事件

mouted(){
 // 设置监听, ctrl + s 保存, ctrl + z 上一步, ctrl + y 下一步
 document.addEventListener('keydown', this.onCtrlEvent)
}

2. 编写执行函数

onCtrlEvent(e) {
  if (e.ctrlKey && e.code === 'KeyS') { // ctrl+s 保存
    // 保存 fun()
    e.preventDefault()
  } else if (e.ctrlKey && e.code === 'KeyZ') { // ctrl+z 上一步
    // 上一步 fun()
    e.preventDefault()
  } else if (e.ctrlKey && e.code === 'KeyY') { // ctrl+y 下一步
    // 下一步 fun()
    e.preventDefault()
  }
}

3. 在 destroyed 中移除监听事件,以免全局作用

destroyed() {
    document.removeEventListener('keydown', this.onCtrlEvent)
  }


Vue2:v-bind="$attrs"多层级组件传参

第一层组件正常传参
第一层组件

中间组件使用 v-bind=“$attrs”,可以简化代码
在这里插入图片描述
在这里插入图片描述

接受参数组件正常接收参数
在这里插入图片描述
来自大佬的评论补充:
v-bind="$attrs"如果要全部传到第三层,那么需要中间组件不能在 props 中接收参数,如果在中间组件的 props 里面接收到了一部分参数,那么传到下一层的应该只是剩余参数了,并且默认中间组件未使用的参数显示在中间件的dom元素上



Vue2:调用父组件或子组件的属性以及方法 $parent / $refs

例如组件层级为 A ====> B ====> C

B 组件调用父组件 A 的方法以及属性

this.$parent.方法名()
this.$parent.属性名

B 组件调用子组件 C 的方法以及属性

this.$refs.子组件的ref名.方法名()
this.$refs.子组件的ref名.属性名


Vue2:数字切换滚动样式

依赖组件于 vue-digital-transform
1. 下载组件

npm i vue-digital-transform --save

2. 引用组件

import DigitalTransform from 'vue-digital-transform'

3. 使用组件

<DigitalTransform
	:value="number"
	:interval="interval"
	:dislocation="dislocation">
</DigitalTransform>

4. 全部代码

<template>
  <div class="hello-world">
    <div class="number">
      <DigitalTransform
        :value="number"
        :interval="interval"
        :dislocation="dislocation"
      ></DigitalTransform>
    </div>

    <div class="control">
      <button @click="changeNumber">change</button>
    </div>
  </div>
</template>

<script>
import DigitalTransform from 'vue-digital-transform';

export default {
  components: {
    DigitalTransform,
  },
  
  data() {
    return {
      number: 1000, // 展示数字
      interval: 500, // 切换时间
      dislocation: false, // 错位
    };
  },
  
  methods: {
  	// 随机切换数字
    changeNumber() { 
      this.number = Math.round(Math.random() * 1000);
    },
  },
};
</script>
<style lang="less" scoped>
.hello-world {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  .number {
    width: 100%;
    height: 80px;
    line-height: 80px;
    font-size: 80px;
    color: green;
    display: flex;
    justify-content: center;
  }
}
</style>


vue2: 父子组件生命周期函数执行顺序

  • 加载渲染过程
    在这里插入图片描述

  • 子组件更新过程
    在这里插入图片描述

  • 父组件更新过程
    在这里插入图片描述

  • 销毁过程
    在这里插入图片描述



Vue3:toRaw 方法和 markRow 方法

在 setup 函数中,我们使用 ref 函数和 reactive 函数将基本数据或者对象数据创建成 Proxy 代理对象(响应式数据),以达到双向绑定的目的,但是某些情况下我们不需要对其进行双向绑定,这导致性能的消耗,尤其是当对象的内容很多的时候,会导致页面的卡顿。
toRaw函数: 通过该方法我们获取 Proxy 代理对象包装前的原始数据,下面是简单的例子

import { reactive, toRaw } from "vue";
export default {
  setup() {
  	// 获取 reactive 包装的原始数据
    const obj1= {name:'崔堂袁'};
    const user = reactive(obj1);
    const obj2 = toRaw(user);
    console.log(obj1 === obj2); //true
    
    // 获取 ref 包装的原始数据
    const ctyAge1 = ref(24);
    const ctyAge2 = toRaw(ctyAge.value); // ctyAge === 24 ? true
    
    return {..................};
  },
};

注意:ref 包装的为什么要用 .value ?因为 ref 的本质还是 reactive,即 ref( obj ) 相当于 reactive( { value: obj } )

markRaw 函数: 用该方法标记的对象永远不会被追踪,简单理解就是不会给被 markRaw 标记的对象创建响应式数据,就算标记之后用 reactive 将其包装成 Proxy,不报错,也不会被创建成 Proxy 代理对象。该方法本质是为源对象增加一个属性标志__v_skip: true,意思是告诉 vue,若要代理该对象,请跳过处理,简单的例子在下面。

import { reactive, markRaw } from "vue";
export default {
  setup() {
  	
  	const obj = markRaw( { name: 'cty', age: 24 } )
    const objUser = reactive(obj)
    console.log(objUser) // {name: 'cty', age: 24, __v_skip: true}
    
    return {..................};
  },
};


vue3: i18n语言包的配置使用

1. 下载最新版本的 i18n 模块

npm install vue-i18n@next

目前使用 npm install vue-i18n 下载的版本是不支持 vue3.x 的,所以使用上面的代码获取最新的版本

2. 在 src 目录下创建一个文件夹 language,并在 language 下创建配置文件 index.js、中文包文件 cn.js、英文包文件 en.js,当然还可以创建更多,这里就使用中英两种语言举例

在这里插入图片描述
3. 编辑三个文件内容

language/index.js

import { createI18n } from 'vue-i18n' //引入 vue-i18n 组件
  //注册i8n实例并引入语言文件
 const i18n = createI18n({
    locale: 'ch',		//默认显示的语言 
      messages: {
        ch:require('./ch.js'),	//引入语言文件
        en:require('./en.js')
      }
  })
  export default i18n; //将i18n暴露出去,在main.js中引入挂载

language/cn.js

export const lang = {
  welcomeTitle: '欢迎来到基于Vue.js和webGL的三维场景开发网!',
  loginModal: {
    modalTitle: '请登录',
    loginTitle: '请输入您的账号和密码!',
    account: '账号',
    inputAccountTitle: '请输入账号',
    accountErrorTitle: '该账号不存在!',
    passWord: '密码',
    inputPassWordTitle: '请输入密码',
    passWordErrorTitle: '密码错误!',
    loginSuccess: '登陆成功!',
    registerLink: '没有账号?注册一个',
    login: '登录',
    cancel: '取消',
    unknownexception: '未知异常'
  }
}

language/en.js

export const lang = {
  welcomeTitle: 'Welcome to the 3D scene development network based on Vue.js and webGL!',
  loginModal: {
    modalTitle: 'Please Sign In',
    loginTitle: 'Please enter your account and password!',
    account: 'Account',
    inputAccountTitle: 'Please input your account',
    accountErrorTitle: 'The account does not exist!',
    passWord: 'Password',
    inputPassWordTitle: 'Please input your password',
    passWordErrorTitle: 'Wrong password!',
    loginSuccess: 'login successful!',
    registerLink: 'Don\'t have an account? Register one',
    login: 'Sign In',
    cancel: 'Cancel',
    unknownexception: 'Unknown exception'
  }
}

4. 在 main.js 中全局挂载

import { createApp } from 'vue'
import App from './App.vue'
import VueI18n from './language'

const app = createApp(App) // 创建 app 实例

app
  .use(VueI18n)
  .mount('#app')

5. 在 vue 文件中使用

<div class="title">{{$t('lang.welcomeTitle')}}</div>
import { getCurrentInstance } from 'vue'
import { useI18n } from 'vue-i18n'
import { message } from 'ant-design-vue'
export default {
  setup () {
    const { proxy } = getCurrentInstance() // 获取全局对象
    const { t } = useI18n()
    const aaa = () => {
      // 可通过全局对象找到 $t
      message.success(proxy.$t('lang.welcomeTitle')) 
      // 也可直接使用 useI18n 的方式
      message.success(t('lang.welcomeTitle')) 
    }
  }
}

6. 切换语言

import { useI18n } from 'vue-i18n'
export default {
  setup () {
    const { locale } = useI18n()
    const changeLaguage = (value) => {
      locale.value = value // value='cn'||'en'
    }
  }
}


Vue3: 自定义指令 + ResizeObserver 实现对元素的宽高以及显隐监听

ResizeObserver API 介绍

ResizeObserver 接口避免了自身回调中调整大小从而触发的无限回调和循环依赖,相对于 window 的 resize 事件,这个 API 在开发过程中可以极大的提高性能,并且 window 的 resize 事件只能监听浏览器的窗口大小变化,不能直接监听具体的某个元素(至少我没找到它的实现方法),所以ResizeObserver 就发挥它的作用了。
ResizeObserver 可以帮助我们:监听一个Dom节点的变化,这种变化包括但不仅限于:
1. 某个节点的出现和隐藏
2. 某个节点的大小变化
ResizeObserver API 是一个新的 JavaScript API,与 IntersectionObserver API 非常相似,它们都允许我们去监听某个元素的变化。
实际上,ResizeObserver API 使用了观察者模式,也就是我们常说的发布-订阅模式。发布-订阅模式是 JavaScript 中典型的设计模式,在很多地方都有使用到。如 Nodejs 的 Event 模块,Vue 的父子组件通信等等。

ResizeObserver API 用法

使用 ResizeObserver API 非常简单。ResizeObserver 是个构造函数。在使用 new 关键字调用构造函数,返回实例对象时,需要传入一个回调函数,这个回调用于监听实例对象某个 DOM 节点的变化。如:

const myObserver = new ResizeObserver(entries => {
	entries.forEach(entry => {
		console.log('大小位置', entry.contentRect)
		console.log('监听的DOM', entry.target)
	})
})
myObserver.observe(document.body)

以上,调用实例对象的 observe 方法,监听整个 body 节点的变化,当改变窗口大小或者某个 DOM 节点出现或隐藏时时,就会触发回调。
如果想在监听多个 DOM 节点的变化,直接在一个实例对象上调用多次 observe 方法就好了。如:

const myObserver = new ResizeObserver(entries => {
// 注意,entres是个数组,数组项为每个需要监听的DOM节点
   entries.forEach(entry => {
     console.log('大小位置 contentRect', entry.contentRect)
     console.log('监听的DOM target', entry.target)
   })
})
myObserver.observe(document.body)
myObserver.observe(document.querySelector('#app'))

实例对象 myObserver 方法除了有 observe 方法之外,还有 disconnect 方法和 unobserve 方法。
unobserve 方法,顾名思义了,就是取消监听某个DOM节点。
disconnect 方法,取消对所有节点的监听。

在使用 API 的时候,有些情况下可能会出现一秒钟调用很多次回调函数,如果想要进一步优化性能,加上节流函数即可。

Vue3 自定义指令介绍

额,这个。。。这不需要我介绍吧,这个很基础的啊,这个只有菜鸡才不会的好不啦😎。为了摆脱菜鸡这个称号,俺在写这篇文章的前半个小时一不小心学会了这个技能。。。话不多说,上链接:
Vue官网:自定义指令的基本使用

我用八千匹垂垂老矣、将死的老牛把话题拉回来,用文人雅士的话来说就是言归正传,回到我们结合 自定义指令 + ResizeObserver API 实监听某个元素的大小变化上面:
首先?其次?最后???哪有那么多过场,直接上代码:

<template>
  <div class="hello" v-resize @click="e => chengeElWidth(e)">
    {{title}}
  </div>
</template>

<script>
import { reactive, toRefs, onMounted } from 'vue'
export default {
  components: {},
  // 自定义局部指令
  directives: {
    resize: {
      // 在绑定元素的父组件被挂载后调用
      mounted (el, binding) {
        let resizeObserver = new ResizeObserver(() => {
          binding.instance.resizeFun(el)
        })
        // 开始观察指定的 Element
        resizeObserver.observe(el)
      }
    }
  },
  setup () {
    const state = reactive({
      title: '我是崔堂袁',
      boxWidth: 100
    })
    onMounted(() => { })
    const chengeElWidth = (e) => {
      e.target.style.width = `${state.boxWidth}px`
      state.boxWidth += 50
    }
    const resizeFun = (el) => {
      console.log(el.clientWidth)
    }

    return {
      ...toRefs(state),
      chengeElWidth,
      resizeFun
    }
  }
}
</script>

搞定!!!



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值