计算机系统应用教程网站

网站首页 > 技术文章 正文

VUE 技术栈

btikc 2024-09-05 12:47:17 技术文章 15 ℃ 0 评论

官网链接:

https://cn.vuejs.org/

什么是vue:

渐进式JavaScript 框架

vue-cli链接:

https://cli.vuejs.org/

vue-cli安装:

npm install -g @vue/cli

vue -V

创建一个项目:

vue create xxxxxx

模版语法:

文本插值 {{ }}

<span>Message: {{ msg }}</span>

原始 HTML v-html

<p>Using text interpolation: {{ rawHtml }}</p>

<p>Using v-html directive: <span v-html="rawHtml"></span></p>

Attribute 绑定

<div v-bind:id="dynamicId"></div>

简写 <div :id="dynamicId"></div>

同名简写 <div :id></div>

布尔型 Attribute

<button :disabled="isButtonDisabled">Button</button>

isButtonDisabled真值或一个空字符串 (即 <button disabled="">) 时,

元素会包含这个 disabled attribute。而当其为其他假值时 attribute 将被忽略。

动态绑定多个值

const objectOfAttrs = { id: 'container',class: 'wrapper' }

<div v-bind="objectOfAttrs"></div>

使用 JavaScript 表达式

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div :id="`list-${id}`"></div>

调用函数

<time :title="toTitleDate(date)" :datetime="date">{{ formatDate(date) }}</time>

条件渲染:

<div v-if="type === 'A'">A</div>

<div v-else-if="type === 'B'">B</div>

<div v-else-if="type === 'C'">C</div>

<div v-else>Not A/B/C</div>

也可以在 <template> 上使用

<h1 v-show="ok">Hello!</h1>

v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。

因此,如果需要频繁切换,则使用 v-show 较好;

如果在运行时绑定条件很少改变,则 v-if 会更合适

v-ifv-for 同时存在于一个元素上的时候,v-if 会首先被执行

双向绑定:

v-model

<input v-model="text">

Class 与 Style 绑定:

<div :class="{ active: isActive }"></div>

上面的语法表示 active 是否存在取决于数据属性 isActive真假值

const classObject = reactive({ active: true,'text-danger': false })

<div :class="classObject"></div>

绑定一个数组来渲染多个 CSS class

<div :class="[activeClass, errorClass]"></div>

绑定内联样式

<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

const styleObject = reactive({ color: 'red',fontSize: '30px' })

<div :style="styleObject"></div>

路径替代:

@ 代表src根路径

<img :src='@/assets/a.png' />

模板中用到的图片,可以放置在assets目录

在数据中定义的路径,图片放置publuc目录

事件处理:

用法:v-on:click="handler"@click="handler"

<button @click="count++">Add 1</button>

<p>Count is: {{ count }}</p>

<!-- 使用特殊的 $event 变量 -->

<button @click="warn('Form cannot be submitted yet.', $event)">Submit</button>

<!-- 使用内联箭头函数 -->

<button @click="(event) => warn('Form ', event)">Submit</button>

function warn(message, event) {

// 这里可以访问原生事件

if (event) { event.preventDefault() }

alert(message)

}

事件修饰符

<!-- 单击事件将停止传递 -->

<a @click.stop="doThis"></a>

<!-- 提交事件将不再重新加载页面 -->

<form @submit.prevent="onSubmit"></form>

<!-- 修饰语可以使用链式书写 -->

<a @click.stop.prevent="doThat"></a>

<!-- 也可以只有修饰符 -->

<form @submit.prevent></form>

<!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->

<!-- 例如:事件处理器不来自子元素 -->

<div @click.self="doThat">...</div>

页面自适应:

解决方案,引入淘宝的自适应js

  • 局部就在页面引入
  • 全局就在main引入

组件:

import { ref } from 'vue'

export default {

setup() {

const count = ref(0)

return { count }

},

template: `<button @click="count++">You clicked me {{ count }} times.</button>`

// 也可以针对一个 DOM 内联模板:

// template: '#my-template-element'

}

样式局部化:

<style scoped ></style>

原理

在节点添加自定义属性 data-v-xxx

根据属性选择器添加样式

插槽:

<slot></slot>

<FancyButton>Click me!</FancyButton> <!-- 插槽内容 -->

<button class="fancy-btn"><slot></slot> </button><!-- 插槽出口 -->

具名插槽 <slot> 元素可以有一个特殊的 attribute name

<div class="container">

<header><slot name="header"></slot></header>

<main><slot></slot></main>

<footer><slot name="footer"></slot></footer>

</div>

<template v-slot:header> 可以简写为 <template #header>

<BaseLayout>

<template v-slot:header></template><!-- header 插槽的内容放这里 -->

</BaseLayout>

插件:

下载插件

引用

全局在main导入

局部在组件导入

配置

样式穿透:

::v-deep 通用

>>>

/deep/

生命周期:

data:

export default {

data(){

age = 11 //静态属性不能双向绑定

return { name: 'xxxx' } //属性双向绑定

},

methods:{ //调用多次,执行多次

newName() { this.name = 'yyyy' }

},

computed:{ //计算属性有缓存,只计算一次

changeName(){ return this.name + 'aa'} //不能修改

changeAge(){//这种写法可以修改

get() { return this.age},

set( val ){ this.age = val }

}

}

}

axios二次封装:

import axios from 'axios';

const service = axios.create({// 创建axios实例

baseURL: process.env.VUE_APP_BASE_API, // api的base_url

timeout: 5000 // 请求超时时间

});

service.interceptors.request.use(// 请求拦截器

config => {

// 可以在这里添加请求头等信息

return config;

},

error => {

// 请求错误处理

console.log(error); // for debug

Promise.reject(error);

}

);

service.interceptors.response.use(// 响应拦截器

response => {

// 对响应数据做处理,例如只返回data部分

return response.data;

},

error => {

// 响应错误处理

console.log('err' + error); // for debug

return Promise.reject(error);

}

);

export default service;

解耦:

import service from '@/utils/request';

// 获取用户列表

export function getUserList(params) {

return service({

url: '/user/list',

method: 'get',

params

});

}

调用:

getUserList({ page: 1, pageSize: 10 }).then(data => {

console.log(data);

});

路由:

<div id="app">

<p>

<!-- 使用 router-link 组件来导航. 通过传入 `to` 属性指定链接. -->

<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->

<router-link to="/foo">Go to Foo</router-link>

<router-link to="/bar">Go to Bar</router-link>

</p>

<!-- 路由出口 路由匹配到的组件将渲染在这里 -->

<router-view></router-view>

</div>

// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义 (路由) 组件。可以从其他文件 import 进来

const Foo = { template: '<div>foo</div>' }

const Bar = { template: '<div>bar</div>' }

// 2. 定义路由

// 每个路由应该映射一个组件。 其中"component" 可以是

// 通过 Vue.extend() 创建的组件构造器,

// 或者,只是一个组件配置对象。

// 我们晚点再讨论嵌套路由。

const routes = [{ path: '/foo', component: Foo },{ path: '/bar', component: Bar }]

// 3. 创建 router 实例,然后传 `routes` 配置

// 你还可以传别的配置参数, 不过先这么简单着吧。

const router = new VueRouter({

routes // (缩写) 相当于 routes: routes

})

// 4. 创建和挂载根实例。 记得要通过 router 配置参数注入路由,

// 从而让整个应用都有路由功能

const app = new Vue({ router }).$mount('#app')

路由守卫:

全局前置守卫:

router.beforeEach((to, from, next) => {

if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })

// 如果用户未能验证身份,则 `next` 会被调用两次

next()

})

组件内守卫:

beforeRouteEnter(to, from, next) {

// 在渲染该组件的对应路由被 confirm 前调用

// 不!能!获取组件实例 `this`

// 因为当守卫执行前,组件实例还没被创建

},

beforeRouteUpdate(to, from, next) {

// 在当前路由改变,但是该组件被复用时调用

// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,

// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。

// 可以访问组件实例 `this`

},

beforeRouteLeave(to, from, next) {

// 导航离开该组件的对应路由时调用

// 可以访问组件实例 `this`

}

路由独享守卫:

const router = new VueRouter({

routes: [{

path: '/foo',

component: Foo,

beforeEnter: (to, from, next) => {// ...}

}]

})

watcher 函数:

a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},

// 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},

// 该回调将会在侦听开始之后被立即调用
d: {
handler: 'someMethod',
immediate: true
},

vuex:

持久化数据:

npm install vuex-persistedstat

vue.config.js配置:

https://blog.csdn.net/muzidigbig/article/details/115665717

output.path:硬盘上的路径,也就是你打算把文件打包到你的哪个目录,也就是各个牛人说的绝对路径!与发布时的路径完全无关。

output.publicPath:主要用来转换url中的相对路径的。如果你引用到包含url的资源,一定要配置output.publicPath。配置了此项,webpack在打包时才能根据配置动态修改uri中的相对值。

-------------------------------------------------------------------------------------------------------------------------

NUXTJS 2 框架:

安装: npx create-nuxt-app <项目名>

选择安装项目:

生命周期:

nuxtServerInit,在store文件夹下建立index.js文件。

此生命周期会全局运行,无论访问那个vue文件,都会走

nuxtServerInit 可接收两个参数store,content

  export const state = {
    token: "123456",
  };
  export const mutations = {
    setToken(state, token) {
      state.token = token;
    },
  };
  export const actions = {
    /**
     *
     * @param {*} store 可获取到vuex上下文的数据
     * @param {*} content 可获取到nuxt上下文的数据
     */
    nuxtServerInit(store, content) {
      store.commit("setToken", "abc123");
      console.log("nuxtServerInit", store);
    },
  };

middleware 中间件,第二个生命周期,也是执行每个vue文件都会运行的

需先在nuxt.config.js中进行配置router,设置的是全局middleware中间件

项目根目录下建立middleware文件夹,再建auth.js文件

export default function ({ store, route, redirect, params, query, req, res }) {
  // 根据获取到的参数,可以去判断路由跳转到哪个具体页面,或者根据参数去处理下其他逻辑
  console.log("middleware auth");
}


也可以设置局部的中间件,如建立一个list.vue,

middleware文件夹下建立一个list.js,调用如下:

list.vue

<template>
  <div>list 页面</div>
</template>
<script>
export default {
  name: "list",
  middleware: "list",  // 使用局部的中间件
  // 第二种写法如下
  middleware(){
      console.log('middleware list 局部')
  }
};
</script>

list.js

export default function () {
  console.log("middleware list 局部");
}

全局的中间件会先执行,然后再执行局部的中间件

validate 校验路由参数的,第三个生命周期执行,一般写在vue文件里

<template>
  <div>
    首页
    <Tutorial />
  </div>
</template>

<script>
export default {
  name: "IndexPage",
  validate({ params, query }) {
  // 判断路由传参对不对,若是不符合规范,则可让页面跳转到404页面,不至于页面出现空白情况
    console.log("validate");
    return true;
  },
};
</script>

asyncData 方法会在组件(限于页面组件)每次加载之前被调用。

它可以在服务端或路由更新之前被调用。

在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,

你可以利用 asyncData方法来获取数据并返回给当前组件

// 注意:由于asyncData方法是在组件 初始化 前被调用的,
//所以在方法内是没有办法通过 this 来引用组件的实例对象。
 asyncData({ store, params }) {
 // 再此可调用接口,请求数据
    console.log("asyncData");
  },

fetch 方法的第一个参数是页面组件的上下文对象 context,

我们可以用 fetch 方法来获取数据填充应用的状态树。

为了让获取过程可以异步,你需要返回一个 Promise,

Nuxt.js 会等这个 promise 完成后再渲染组件。

// 警告: 您无法在内部使用this获取组件实例,fetch是在组件初始化之前被调用
fetch({ app, store, params }) {
    console.log("fetch");
 },

服务端与客户端共有的生命周期

接下来是vue中生命周期,比较常用,就不做解释里。

  • beforeCreate
  • created

客户端的生命周期

  • beforeMount() {},
  • mounted() {},
  • beforeUpdate() {},
  • updated() {},
  • beforeDestroy() {},
  • destroyed() {},

路由:

重构引用原来的router文件

持久化数据:

style:

nuex.config.js配置,全局样式

使用scss步骤

  • 安装插件
  • 标记 scoped lang

plugins:

定义全局插件或者第三方插件配置,在页面之前调用

element-ui引用配置

axios:


配置代理:

loading:

重构:

npm install vue-verify-plugin -S


项目上线:

-------------------------------------------------------------------------------------------------------------------------

VUE 3

脚手架:

什么是vite,vite是构建工具,vite 开发效率高

vue-cli 2.0 | 3.0, vue create xxx ,是基于webpack构建

vite创建项

npm init @vitejs/app xxx

创建router文件夹,新建index.js文件

解决@根目录导入问题

定义数据:

数据截持原理:

setup语法糖插件:

npm install unplugin-auto-import

torefs:

结构数据转变响应式

watch:

生命周期:

路由:


组件传参:

父传子

子传父

兄弟之间传值:

插槽:

传送:

动态组件:

异步组件:

https://vueuse.nodejs.cn/core/useIntersectionObserver/

组件按需引入,用户访问到了该组件再加载组件

场景一

import { useIntersectionObserver } from '@vueuse/core'

const target = ref(null)

const targetIsVisible = ref(false)

const { stop } = useIntersectionObserver( target, ([{ isIntersecting }], observerElement) => { targetIsVisible.value = isIntersecting }, )

<template> <div ref="target"> <h1>Hello world</h1> </div> </template>

场景二

美 [s??spens]

场景三

混入:

mixin,分发vue组件中的可复用的功能

创建文件夹mixins,新建文件mixin.js

setup写法

选项势写法:

依赖注入:

provider | inject

vuex:

pinia:

安装

npm install pinia

创建文件夹store,新建文件index.js

组件中使用

持久化

设置代理

登录加密:

一、安装 crypto-js npm install crypto-js

二、引入crypto-js 支持ES6导入、Modular

import CryptoJS from "crypto-js"; 或者 const CryptoJS = require("crypto-js");

三、设置密钥和密钥偏移量

// 十六位十六进制数作为密钥

const SECRET_KEY = CryptoJS.enc.Utf8.parse("1234123412341234");

// 十六位十六进制数作为密钥偏移量

const SECRET_IV = CryptoJS.enc.Utf8.parse("1234123412341234");

四、封装加密方法

/* 加密方法 @param data @returns {string} */

export function encrypt(data) {

if (typeof data === "object") {

try {

// eslint-disable-next-line no-param-reassign

data = JSON.stringify(data);

} catch (error) {

console.log("encrypt error:", error);

}

}

const dataHex = CryptoJS.enc.Utf8.parse(data);

const encrypted = CryptoJS.AES.encrypt(dataHex, SECRET_KEY, {

iv: SECRET_IV,

mode: CryptoJS.mode.CBC,

padding: CryptoJS.pad.Pkcs7

});

return encrypted.ciphertext.toString();

}

五、封装解密方法

/* 解密方法 @param data @returns {string} */

export function decrypt(data) {

const encryptedHexStr = CryptoJS.enc.Hex.parse(data);

const str = CryptoJS.enc.Base64.stringify(encryptedHexStr);

const decrypt = CryptoJS.AES.decrypt(str, SECRET_KEY, {

iv: SECRET_IV,

mode: CryptoJS.mode.CBC,

padding: CryptoJS.pad.Pkcs7

});

const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);

return decryptedStr.toString();

}

六、使用方法

import { decrypt, encrypt } from "@/utils/encrypt";

const data = "13172"

const encryptText = encrypt(data);

console.log("加密", encryptText);

const decryptText = decrypt(encryptText);

console.log("解密", decryptText);

解决 vite 不能使用 require

文件下载

视频播放


-------------------------------------------------------------------------------------------------------------------------

NUXT3

安装:

npx nuxi@latest init <project-name>

安装失败解决方法:

运行项目:

  • cd 到目录执行 npm i
  • npm run dev

文件路由:

seo优化:

useSeoMeta({

title:'',

...

})

https://nuxt.com/docs/getting-started/seo-meta

组件库安装:

npm i @vant/nuxt

nuxt.config.js配置

接口:

export default defineEventHandler(async (event) => { // ... Do whatever you want here })

请求数据:

const { data: count} = awaituseFetch('/api/count')

浏览器插件:

vs插件:


预渲染解决方案:

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表