# 监听屏幕尺寸变化

Vue中可以使用window的所有方法

mounted() {
    this.screenWidth = document.body.clientWidth
	window.onresize = () => {
	  return (() => {
		this.screenWidth = document.body.clientWidth
	  })()
	}
}

# template 占位符

template可以起到block的作用,但是v-for时不能加key

注意

v-if和v-for不可以一起使用的,v-for 具有比 v-if 更高的优先级

# 出现data-v-xxx的原因

在Vue开发中,会遇到html被浏览器解析后,在标签中出现'data-v-xxxxx'标记,如下:

<div data-v-fcba8876 class="xxx"> aaa</div>

这是在标记vue文件中css时使用scoped标记产生的,因为要保证各文件中的css不相互影响,给每个component都做了唯一的标记,所以每引入一个component就会出现一个新的'data-v-xxx'标记。

# node/node-sass/sass-loader版本兼容

node16+ 对应的node-sass,sass-loader版本

"sass-loader": "^10.2.0",
"node-sass": "^6.0.1",

sass-loader 4.1.1,node-sass 4.3.0
sass-loader 7.0.3,node-sass 4.7.2
sass-loader 7.3.1,node-sass 4.7.2
sass-loader 7.3.1,node-sass 4.14.1

node18+ 对应的版本

"node-sass": "^8.0.0",
"sass-loader": "^10.4.1",

# 清除浏览器自动填充表单账号密码

普通文本框添加 autocomplete="off",密码输入框添加autocomplete="new-password"

<input type="text" autocomplete="off" name="username"/>
<input type="password" autocomplete="new-password" name="password"/>

# 加载public和src/assets下文件的区别

public 文件夹

  • 路径设置时无需添加 public,默认加载 public下的文件
  • 不需要使用 require,否则就变成在 src/assets 下寻找
  • 系统编译后,文件可替换
this.imgUrl = 'images/test.jpg';
// 或
this.imgUrl = './images/test.jpg';

src/assets 文件夹

  • 需要使用 require、import、new URL(),运行时就加载
  • 系统编译后,不能替换,因为被内部编译管理
//仅支持在webpack环境中使用,vite中无法支持
this.imgUrl = require('../assets/images/test.jpg');
import imageIcon from '../../../assets/billboard.png'

//vite中支持
const url = new URL('./src', import.meta.url)

# 背景图片路径

# css外设置background-image

在css外设置background-image时,不能直接使用url,应该使用

<li  :style="'background-image:url(require('./../assets/banner_top2.png'))'"></li>

# css内设置background-image

background: url('~@/assets/images/nav/broadcast@2x.png') no-repeat center;

# v-model为空时placeholder不显示

<a-select v-model='a' placeholder="请选择"  >

//解决方案是将a设置为undefined
data() {
  return {
    a:''
  };
}

# 修改checkbox值没有触发change事件

用 js 去修改 checkbox 的 checked 属性,不会触发change事件,所以想要监听 checkbox 的变化,只能:

  • 用户的操作用 change 事件监听
  • 自己用 js 修改的时候,自己在后面写处理函数
<!DOCTYPE html>
<html>
<head>
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
	<section id="app">
		<button @click="flag=!flag">切换!</button>
		<input type="checkbox" v-model="flag" @change="handleChange">
	</section>
	<script>
		var app = new Vue({
			el: '#app',
			watch: {
				flag(val) {
					console.log("监听到flag变化:", val);
				}
			},
			data: {
				flag: true,
			},
			methods: {
				handleChange() {
					console.log("触发change事件");
				}
			}
		})
	</script>
</body>
</html>

# props传递数据有延迟如何解决

先判断是否为空再渲染

<footView :details="details" v-if="Object.keys(details).length>0"></footView>

或者是

watch(
    ()=> props.data,
	()=>{
		const arr= props.data.map(item=>({value: item.today_money, name: item.name }))
		console.log(props.data, arr)
})

# 适配屏幕的缩放比

# 在外部创建一个detectZoom.js文件,我是在utils文件夹下

export const detectZoom = () => {
  let ratio = 0,
    screen = window.screen,
    ua = navigator.userAgent.toLowerCase();
  if (window.devicePixelRatio !== undefined) {
    ratio = window.devicePixelRatio;
  } else if (~ua.indexOf('msie')) {
    if (screen.deviceXDPI && screen.logicalXDPI) {
      ratio = screen.deviceXDPI / screen.logicalXDPI;
    }
  } else if (
    window.outerWidth !== undefined &&
    window.innerWidth !== undefined
  ) {
    ratio = window.outerWidth / window.innerWidth;
  }
  if (ratio) {
    ratio = Math.round(ratio * 100);
  }
  return ratio;
};

# 在main.js中引用

m是获取的当前屏幕的缩放比,在通过zoom属性对应缩放。zoom属性用于设置或检索对象的缩放比例。

import { detectZoom } from '@/utils/detectZoom.js';
const m = detectZoom();
document.body.style.zoom = 100 / Number(m);

# ob: Observer 取值

注意这种类型的数据不能直接通过对象或者数组的方式进项获取,需要格式转换

//方法一
JSON.parse(JSON.stringify(this.list))

//方法二
Object.assign({},this.list)

# 深拷贝与浅拷贝

# Object.assign()对象的拷贝

//方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
Object.assign(target, ...sources) //【target:目标对象】 【souce:源对象(可多个)】
//如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖
const object1 = {a: 1,b: 2,c: 3};
const object2 = Object.assign({c: 4, d: 5}, object1);
 
console.log(object1)  // { a: 1, b: 2, c: 3 }
console.log(object2)  // { c: 3, d: 5, a: 1, b: 2 }

注意

对于Object.assign()而言
如果对象的属性值为简单类型string,number,通过Object.assign,得到的新对象为深拷贝
如果属性值为对象或其他引用类型,那对于这个对象而言其实是浅拷贝的

# 深拷贝

针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用


















 
 
 
 
 
 

let obj1 = { a: 0 , b: { c: 0}}; 
let obj2 = Object.assign({}, obj1); 
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} 
 
obj1.a = 1; 
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} 
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} 
 
obj2.a = 2; 
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} 
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
 
obj2.b.c = 3; 
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}} 
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}} 
//最后一次赋值的时候,b是值是对象的引用,只要修改任意一个,其他的也会受影响
 
// Deep Clone (深拷贝)
obj1 = { a: 0 , b: { c: 0}}; 
let obj3 = JSON.parse(JSON.stringify(obj1)); 
obj1.a = 4; 
obj1.b.c = 4; 
console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}

# 对象的合并

其实就是对象的拷贝,o1就是目标对象,后面的是源对象,后面的属性等会拷贝到目标对象

const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
 
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。

# nginx部署vue到二级目录

# 修改conf文件夹中的nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;
       
        location / {
            root  dist;#这里存放的是你根目录的网站文件,可以不用管
            try_files $uri $uri/ /index.html;
            index  index.html index.htm;
        }

        location /admin {
            alias  你新打包的带二级目录的dist文件夹;
            try_files $uri $uri/ /admin/index.html;#这里要加上你的二级目录名称
            index  index.html index.htm;
        }
        
        location /prod-api/{
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header REMOTE-HOST $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://localhost:8080/;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

}

# vue的修改

  • 修改router/index.js

 





export default new Router({
  base:'admin',//添加二级目录的名称
  mode: 'history', // 去掉url中的#
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes
})
  • 修改vue.config。添加admin二级目录名称
publicPath: process.env.NODE_ENV === "production" ? "/admin/" : "/admin/",

# resetFields()重置按钮生效的条件

form 要设置 ref 属性
# 且 ref 属性值要和 this.$refs[formName].resetFields() 中的 formName 一致

表单域 el-form-item 上需要设置 prop 属性
# 表单 rules 规则校验、resetFields() 重置文件清理的都是 prop 属性绑定的字段

# 样式穿透的区别

  • /deep/:在vue3.0之前可使用,例如(复写样式前加/deep/),vue3.0及后使用就会报错
/deep/ .el-input {
    width: 60px;
}
  • :deep:在vue3.0及后使用,替代/deep/
:deep(.el-input) {
    width: 60px;
}
  • >>>:只作用于css,对于less和scss不起作用,如果是less用/deep/:deep,scss的用::v-deep

# Echarts的使用

import * as echarts from 'echarts'

onMounted(()=>{
	var myEcharts = echarts.init(document.getElementById('pie') as HTMLElement);
	const option = {
		……
	}
	myEcharts.setOption(option);
})

# v-on="$listeners"和v-bind="$attrs"

# v-bind="$attrs"

主要用于组件之间的隔代传值

# 如有父组件A,子组件B,孙组件C,A组件中的值需要直接传给C,就需要在B中设置v-bind="$attrs"
# 然后在C组件中用prop接收,此时就直接把值传给了C组件
<!--父组件A-->
<template>
  <B_zujian  msg='123'/>
</template>

<!--子组件B-->
<template>
   <C_zujian v-bind="$attrs"/>
</template>

<!--孙组件C-->
<template>
  <div>A传递过来的值:{{msg}}</div>
</template>
 
<script>
export default {
  name: 'c_zujian',
  props: {
    msg:{ //接收A组件传递的值 msg
      typeof:String,
      default:''
    }
  },
}
</script>

# v-on="$listeners"

允许子组件自动绑定所有从父组件传下来的事件监听器,而不需要在子组件中显式地声明和绑定每个事件

# 如有父组件A,子组件B,孙组件C,如果C向A传递信息,可以使用 v-on="$listeners" 来满足当前需求
<!--C组件-->
<template>
  <div @click="hanleClick">C组件</div>
</template>
 
<script>
hanleClick(){
  this.$emit("transmitNews",'123')
}
</script>

<!--B组件-->
<template>
  <c_zujian v-on="$listeners"/>
</template>

<!--A组件-->
<template>
  <b_zujian @transmitNews='jieShouTransmitNews'/>
</template>

<script>
methods:{
  jieShouTransmitNews(val){
    console.log(val) //123
  }
}
</script>

# 父组件中每次点击按钮重新加载子组件

key 属性不是给开发人员用的,而是用来 给vue 元素渲染的时候用的,每次渲染的时候会去拿这个key 值做对比,如果这一次的key 值和上一次的key值是不一样的才会重新渲染dom 元素,否则保持上一次的元素状态。

<!-----父组件------>
<template>
    <div>
        <div>
            <h1>父级</h1>
            <button @click="handleLoad">点击重新加载子级</button>
        </div>
        <children :key="timer"></children>
    </div>
</template>
<script>
import children from '@/components/parent/children'
export default {
    name: 'parent',
    components: { children },
    data () {
        return {
            timer: ''
        }
    },
    methods: {
        handleLoad () {
            this.timer = new Date().getTime()
        }
    }
}
</script>

<!-----子组件------>
<template>
    <div>
        子级
    </div>
</template>
<script>
export default {
    name: 'children',
    data () {
        return {}
    },
    created () {
        console.log('重新加载啦')
    }
}
</script>