vue3笔记

此帖子为在学习过程中记录的笔记,可能存在错误
内容存在一定程度的摘抄并非纯原创

全局挂载

//main.js
const apps = createApp(App);
// 全局挂载
apps.config.globalProperties.$_lodash = lodash;
// 组件中
import { getCurrentInstance } from 'vue';
let { proxy } = getCurrentInstance();
//取值
let res = proxy.$_lodash.cloneDeep(res0);

获取原始对象 用 toRaw

在ajax请求放入参数的时候可能会用到

  setup() {
    let obj={name:'lj',age:18}
    let state=reactive(obj)
    let obj2=toRaw(state)   
    console.log(obj===obj2); //true
    
    function myFn(){
      obj2.name='zs'
      console.log(state); //Proxy {name: "zs", age: 18}
      console.log(obj2);  //{name: "zs", age: 18}
    }
    return {
      myFn,state
    }
  },

process.cwd()

process.cwd() 方法返回 Node.js 进程的当前工作目录。

import { cwd } from 'process';

console.log(`Current directory: ${cwd()}`);

Env变量和模式

Vite在特殊的 import.meta 中公开环境变量。env对象。一些内置变量在所有情况下都是可用的。
import.meta.env.MODE: {string}应用程序运行的模式。
import.meta.env.BASE_URL:{string}应用程序提供服务的基础url。这由基本配置选项决定。
import.meta.env.PROD: {boolean}是否在生产环境中运行
import.meta.env.DEV: {boolean}应用是否在开发中运行(总是与import.meta.env.PROD相反)

Production Replacement

在生产过程中,这些env变量被静态地替换。因此,必须始终使用完整的静态字符串引用它们。例如,像import.meta这样的动态密钥访问。env[key]不起作用。
它还将替换JavaScript字符串和Vue模板中出现的这些字符串。这应该是一个罕见的情况,但它可能是无意的。有一些方法可以解决这个问题:
对于JavaScript字符串,你可以用一个unicode零宽度的空格来分隔字符串,例如。“import.meta \ u200b.env.MODE”。
对于被编译成JavaScript字符串的Vue模板或其他HTML,你可以使用标签,例如import.meta.env.MODE。

.env Files

Vite使用dotenv从你的项目根目录下的以下文件中加载额外的环境变量:

.env

__dirname

__dirname 是node的一个全局变量,获得当前文件所在目录的完整目录名
当你在 /d1/d2/myscript.js 文件中写了 __dirname, 它的值就是 /d1/d2 。
例如在vite中配置别名

resolve: {
  alias: {
    "@": path.resolve(__dirname, "./src")
  },
},

vite共享配置 mode

类型: string

默认: ‘development’(开发模式),‘production’(生产模式)

在配置中指明将会把 serve 和 build 时的模式 都 覆盖掉。也可以通过命令行 --mode 选项来重写。

export default(({mode})=>{
 return defineConfig({
    plugins: [vue()],
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "./src")
      },
    },
    base: "/",
    build: {
      brotliSize: false,
      chunkSizeWarningLimit: 1024,
    },
    server: {
      // host: "localhost",
      port: 3030,
      // 是否自动在浏览器打开
      open: false,
      // 是否开启 https
      https: false,
      proxy: {
        '/api': {
          target:  loadEnv(mode,process.cwd()).VITE_ADMIN_BASE_API,
          changeOrigin: true,
          rewrite: path => path.replace(/^\/api/, '')
        },
        '/psi': {
          target:  loadEnv(mode,process.cwd()).VITE_PDS_BASE_API,
          changeOrigin: true,
          rewrite: path => path.replace(/^\/psi/, '')
        },
        '/Cti': {
          target:  loadEnv(mode,process.cwd()).VITE_BASE_API,
          changeOrigin: true,
          rewrite: path => path.replace(/^\/Cti/, '')
        }
      },
    },
  });

}) 

关于v3 ref 和 reactive 的坑

reactive 有个比较大的缺点 不能整体重新赋值 重置数据麻烦。想要整体赋值的话需要在对象中创建一个属性 对这个属性进行整体值的切换。最后还是避免不了内部引用。
例如使用element的多选框组 使用 reactive 直接创建一个数组的话是不起作用的

const info = reactive(data:{xxx:'ooo'})
更新时:
info.data = {xxx:'aaa'}
使用ref
const info = ref({xxx:'ooo'})
更新
info.value = {xxx:'aaa'}

总结: 除 对象/json/复杂的嵌套数组外。其他全用 ref :如基本类型、一维数组

关于资源、组件 引入时的后缀

v3的项目中引入组件和api接口的时候,最好把后缀也带上。否则有可能出现找不到模块的问题

v3组件传值

script setup 中的传值方式

  • defineProps
  • defineEmits
  • Provide / Inject

defineProps父传子
和props的用法几乎一样

//子组件中
const props = defineProps({
  foo: String
})
//取值
props.foo

defineEmits子传父
和Emit用法几乎一样

//子组件
let emit = defineEmits(['submission']);
emit('submission',{a:1,b:2});
//父组件
<myCustomTimeSection @submission="customTimeFn" />
let customTimeFn = (val)=>{
	console.log(val)  // {a:1,b:2}
}
	

Provide / Inject
依赖注入
可以将依赖注入看作是“长距离的 prop”除了

  • 父组件不需要知道哪些子组件使用了它 provide 的 property
  • 子组件不需要知道 inject 的 property 来自哪里

Provide
中允许定义两个参数
1、name (String 类型)
2、value

Provide 能够正确传递 ref reactive 的响应式数据,但要尽可能将对响应式property的所有修改限制在provide的组件内部
如果需要Inject接收注入的组件内部更新数据的话。这种情况下最好用Provide传入一个方法来负责在子组件中改变父组件的数据

//父组件
let addClose = ()=> {
  addSwitch.value = false
}
provide('addCloseFn',addClose)
//子组件
<span @click="addCloseFn" >x</span>
const addCloseFn = inject('addCloseFn');

如果要确保通过 provide 传递的数据不会被 inject 的组件更改建议使用 readonly

<script setup >
import { provide, reactive, readonly, ref } from 'vue';
const location = ref('North Pole')
const geolocation = reactive({
  longitude: 90,
  latitude: 135
})
provide('location', readonly(location))
provide('geolocation', readonly(geolocation))
</script>

Inject
1、要 inject 的 property 的 name
2、默认值 (可选)

//子组件中
<script setup >
import { inject } from 'vue'
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
</script>

v3动态组件

如果是在 script setup 单文件组件中使用的话
这时候 组件被引用为变量而不是作为字符串键来注册
所以书写方式要有一定改变

<component :is="currentElementComponent[componentPoint]"></component>
// script setup 中
import { ref } from "vue";
import demonstrationOne from './conView/demonstrationOne.vue'
import demonstrationTwo from './conView/demonstrationTwo.vue'
let currentElementComponent = {
  'demonstrationOne':demonstrationOne,
  'demonstrationTwo':demonstrationTwo
}
let componentPoint = ref('demonstrationOne')

git删除远程仓库链接地址

常用于本地不想影响到远程的时候

//查看当前远程仓库链接
git remote -v
//根据第一步查询出来的链接删除别名即可
git remote rm origin
//git remote -v 没有查询出东西来表示删除成功了

动态组建可以像普通组建一样传值

vue3笔记_第1张图片

插槽传值


Map.vue 组件中
vue3笔记_第2张图片
使用Map.vue组件
vue3笔记_第3张图片

Map.vue 组件
vue3笔记_第4张图片
使用Map.vue 组件
vue3笔记_第5张图片

props

在设置默认值的时候对象或数组的默认值必须从一个工厂函数返回

props: {
    // 基础的类型检查 (`null` 和 `undefined` 值会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组的默认值必须从一个工厂函数返回
      default() {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator(value) {
        // 这个值必须与下列字符串中的其中一个相匹配
        return ['success', 'warning', 'danger'].includes(value)
      }
    },
    // 具有默认值的函数
    propG: {
      type: Function,
      // 与对象或数组的默认值不同,这不是一个工厂函数——这是一个用作默认值的函数
      default() {
        return 'Default function'
      }
    }
  }

slot

无论是使用jsx还是模板,最终都会编译成render函数,并且render函数在执行之后会输出 Virtual Dom

  1. 所有的模板会被编译成创建vnode的函数。
  2. 父组件中传递给子组件的插槽(每个插槽都是一个函数,即名字不同的插槽为不同的函数)内容模板也会被编译成函数并且传递给子组件,模板中如果使用了父组件的变量,那么会通过闭包的形式在插槽函数中被使用。
  3. 子组件在接收到父组件传递的插槽内容函数,会以在slot暴露的变量(只有作用域插槽有这些变量)为参数执行这个函数,返回vnode,这个vnode会作为子组件vnode的一部分。

watch

watch时有一个特点,就是当值第一次绑定时,不会执行监听函数,只有值发生改变时才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,此时就需要deep属性对对象进行深度监听。

vuex 的使用

在setup语法糖中使用vuex

import { useStore } from 'vuex';
const store = useStore();

配合modules使用

import { createStore } from 'vuex'
import monitor from "./modules/monitor.js";
 
export default createStore({
  // 外部模块
	modules:{
	    monitor
	  },
})

monitor 下的 mutations 中的 m_createdDotidentification

store.commit('monitor/m_createdDotidentification');

monitor 下的 state 中的 exhibitionDot

store.state.monitor.exhibitionDot

v3使用全局变量

setup

//main.js
import lodash from 'lodash';
const apps = createApp(App);
apps.config.globalProperties.$_lodash = lodash;
//组件中
import {  getCurrentInstance } from 'vue';
let { proxy } = getCurrentInstance();
proxy.$_lodash.cloneDeep()

选项卡

// main.js
import mitt from "mitt";
const apps = createApp(App);
apps.config.globalProperties.$mybus = new mitt();
//组件中
this.$mybus.on();
this.$mybus.emit();

打开新窗口

let DataUrl = this.$router.resolve({
  path: "/aaa",
  query:{
    ruleChat: row.id
  },
});
window.open(DataUrl.href, "_blanks");

history模式下上线刷新页面404

nginx

location / {
  try_files $uri $uri/ /index.html;
}

这种情况的成因是这样的
history模式是通过js才改变浏览器地址栏的路径,并没有发起http请求。刷新浏览器等于重新发起http请求请求不到对应的参数直接就404了

vite解决跨域问题

实际上跨域方案就这么几个

  1. vue中的proxy跨域(原理是Node中间件代理)
  2. Jsonp跨域
  3. cors (跨域资源共享)
  4. nginx反向代理

这里说一下proxy跨域

vite.config.ts文件中

proxy: {
        "/api": {
          target: 'http://crmeb.cimns.com/api',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, ""),
        },
      },

你可能感兴趣的:(vue.js,javascript)