Vue3
官网:https://v3.cn.vuejs.org/
Vue3 One Piece:https://vue3js.cn/#emits
菜鸟教程:https://www.runoob.com/vue3/vue3-tutorial.html
什么是Vue?
Vue
是一套用于构建用户界面的渐进式框架。
Vue.js
设计的初衷就包括可以被渐进式地采用。这意味着它可以根据需求以多种方式集成到一个项目中。
cnpm(中国 NPM 镜像)
cnpm
官网:https://npmmirror.com/
安装cnpm
npm install -g cnpm --registry=https://registry.npmmirror.com
使用cnpm
安装模块
cnpm install [name]
Vue CLI
Vue CLI
旨在成为Vue
生态系统的标准工具基准。它可确保各种构建工具与合理的默认值一起顺利运行,因此您可以专注于编写应用程序,而不是花费数天时间与配置进行争论。同时,它仍然提供了调整每个工具配置的灵活性,而无需弹出。
安装新程序包
cnpm install -g @vue/cli
cnpm install -g vue-cli cnpm : 无法加载文件 C:\Users\Xiaoyu.Zhang\AppData\Roaming\npm\cnpm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Executio n_Policies。 所在位置 行:1 字符: 1 + cnpm install -g vue-cli + ~~~~ + CategoryInfo : SecurityError: (:) [],PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess
解决方案:
以管理员身份运行
PowerShell
输入
set-ExecutionPolicy RemoteSigned
选择
A
新建一个package.json
文件并初始化
npm init -y
在Vue
项目中运行
vue upgrade --next
创建项目
vue create [app-name]
Vite
下一代前端开发与构建工具
Vite 是一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动。
安装Vite
cnpm install vite
创建项目
npm init @vitejs/app
√ Project name: … vite-test
√ Select a framework: » vue
√ Select a variant: » vue-tsScaffolding project in D:\BSIT_Project\vue-vite-start\vite-project\vite-test…
Done. Now run:
cd vite-test
npm install
npm run dev
安装依赖
cd 项目名
npm i
运行项目
npm run dev
打开网页
http://localhost:3000/
目录结构
目录 / 文件 | 说明 |
---|---|
dist | 使用 npm run build 命令打包后会生成该目录。 |
node_modules | npm 加载的项目依赖模块 |
public | 公共资源目录。 |
src | 这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件: assets: 放置一些图片,如logo等。 components: 目录里面放了一个组件文件,可以不用。 App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。 main.js: 项目的核心文件。 index.css: 样式文件。 |
index.html | 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。 |
package.json | 项目配置文件。 |
README.md | 项目的说明文档,markdown 格式 |
tsconfig.json | |
vite.config.ts |
配置
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
// @ts-ignore
import path from 'path';
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import {ElementPlusResolver} from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
// 在生产中服务时的基本公共路径。类似publicPath,'./'避免打包访问后空白页面,要加上,不然线上也访问不了
base: "./",
resolve: {
// 目录别名
alias: {
"@": path.resolve(__dirname, "src"),
"@assets": path.resolve(__dirname, "src/assets"),
"@components": path.resolve(__dirname, "src/components"),
"@img": path.resolve(__dirname, "src/assets/img"),
"@views": path.resolve(__dirname, "src/views"),
"@store": path.resolve(__dirname, "src/store"),
},
},
// 打包配置
build: {
outDir: "dist", // 指定输出路径
assetsDir: "assets", // 指定静态资源存放路径
sourcemap: false, // 是否构建source map 文件
minify: 'terser', // 混淆器,terser构建后文件体积更小
terserOptions: {
// 生产环境移除console
compress: {
drop_console: true,
drop_debugger: true,
},
},
},
// 本地运行配置,及反向代理配置
server: {
cors: true, // 默认启用并允许任何源
https: false, // 是否开启 https
open: true, // 是否自动在浏览器打开
port: 2048, // 端口号
host: "0.0.0.0",
proxy: {
"/api": {
target: "", // 后台接口(代理接口)
changeOrigin: true,
secure: false, // 如果是https接口,需要配置这个参数
// ws: true, //websocket支持
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
// 引入第三方的配置
optimizeDeps: {
include: ["axios",],
},
})
构建应用
安装vue-tsc
cnpm install vue-tsc
构建
npm run build
Element Plus
官方文档:https://element-plus.gitee.io/zh-CN/
安装
cnpm install element-plus --save
自动导入
安装插件
cnpm install -D unplugin-vue-components unplugin-auto-import
在vite.config.ts
中添加
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
HelloWorld
App.vue
<template>
<div>
{{ msg }}
</div>
<div>
{{ data.data }}
</div>
</template>
<script>
export default {
data() {
return {
msg: "hello world",
data:{
data:[1,2,3,4,5]
}
}
}
}
</script>
Vue语法
插值
文本
<template>
<div>
{{ msg }}
</div>
</template>
<script>
export default {
data() {
return {
msg: "hello world",
}
}
}
</script>
原生html
<template>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
</template>
<script>
export default {
data() {
return {
rawHtml: '<span style="color: red">This should be red.</span>',
}
}
}
</script>
Attribute
<template>
<h1 v-bind:id="msg">Hello World</h1>
</template>
<script>
export default {
data() {
return {
msg: "hello world",
}
}
}
</script>
JavaScript 表达式
每个绑定都只能包含单个表达式
<template>
<p>{{ number + 1 }}</p>
</template>
<script>
export default {
data() {
return {
number:10,
}
}
}
</script>
处理用户输入
事件监听器
v-on
指令添加一个事件监听器
<template>
<div id="event-handling">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转 Message</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue.js!'
}
},
methods: {
reverseMessage() {
this.message = this.message
.split('')
.reverse()
.join('')
}
}
}
</script>
双向绑定
v-model
指令实现表单输入和应用状态之间的双向绑定
<template>
<div id="two-way-binding">
<p>{{ message }}</p>
<input v-model="message" />
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!'
}
}
}
</script>
条件与循环
条件控制
v-if
指令进行条件控制
<template>
<div id="conditional-rendering">
<span v-if="see">现在你看到我了</span>
</div>
</template>
<script>
export default {
data() {
return {
see: true,
// see:false,
}
}
}
</script>
v-for
指令可以绑定数组的数据来渲染一个项目列表
<template>
<div id="list-rendering">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
</template>
<script>
export default {
data() {
return {
todos: [
{text: 'Learn JavaScript'},
{text: 'Learn Vue'},
{text: 'Learn JavaScript'},
{text: 'Learn Vue'},
{text: 'Learn JavaScript'},
{text: 'Learn Vue'},
{text: 'Learn JavaScript'},
{text: 'Learn Vue'},
{text: 'Learn JavaScript'},
{text: 'Learn Vue'},
{text: 'Build something awesome'},
]
}
}
}
</script>
计算属性
为了避免在模板中放入太多的逻辑,使模板过重且难以维护,对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。
<template>
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</div>
</template>
<script>
export default {
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
},
computed: {
// 计算属性的 getter
publishedBooksMessage() {
// `this` 指向 vm 实例
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
}
</script>
侦听器
当需要在数据变化时执行异步或开销较大的操作时,watch
选项提供了一个更通用的方法来响应数据的变化。
但是要避免侦听器的滥用!
<template>
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question" />
</p>
<p>{{ answer }}</p>
</div>
</template>
<!--<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>-->
<script>
export default {
data() {
return {
question: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// 每当 question 发生变化时,该函数将会执行
question(newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1) {
this.getAnswer()
}
}
},
methods: {
getAnswer() {
this.answer = 'Thinking...'
axios
.get('https://yesno.wtf/api')
.then(response => {
this.answer = response.data.answer
})
.catch(error => {
this.answer = 'Error! Could not reach the API. ' + error
})
}
}
}
</script>
选项式API
// src/components/UserRepositories.vue
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: {
type: String,
required: true
}
},
data () {
return {
repositories: [], // 1
filters: { ... }, // 3
searchQuery: '' // 2
}
},
computed: {
filteredRepositories () { ... }, // 3
repositoriesMatchingSearchQuery () { ... }, // 2
},
watch: {
user: 'getUserRepositories' // 1
},
methods: {
getUserRepositories () {
// 使用 `this.user` 获取用户仓库
}, // 1
updateFilters () { ... }, // 3
},
mounted () {
this.getUserRepositories() // 1
}
}
组合式API
<script lang="ts" setup>
import {ref, watch} from 'vue'
import {
Location,
Document,
Menu as IconMenu,
Setting,
} from '@element-plus/icons-vue'
// 定义一个变量
let isCollapse = ref(true)
// 定义方法
const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const changeCollapse = () => {
console.log("点击")
isCollapse.value = !isCollapse.value
return {
isCollapse
}
}
// 监听变量变化
watch(isCollapse, (newVal, oldVal) => {
console.log(newVal, oldVal)
})
</script>
组件
定义子组件
src\componentsHelloWorld.vue
<template>
<h1>{{ msg }}</h1>
</template>
<script lang="ts">
export default {
name: "Hello World"!,
props: {
msg: String,
}
}
</script>
<style>
</style>
src\componentsHelloWorld1.vue
<template>
<h1>{{ msg }}</h1>
</template>
<script lang="ts">
export default {
name: "HelloWorld1",
props: {
msg: String,
}
}
</script>
<style>
</style>
src/App.vue
<template>
<h2>组件测试</h2>
<HelloWorld msg="HelloWorld组件"></HelloWorld>
<HelloWorld1 msg="HelloWorld1组件"></HelloWorld1>
</template>
<script lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
import HelloWorld1 from "./components/HelloWorld1.vue";
export default {
name: "App",
components: {HelloWorld, HelloWorld1}
}
</script>
<style>
</style>
组件传值
父组件向子组件传值
通过props
Prop类型
-
数组形式
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
-
对象形式
props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object, callback: Function, contactsPromise: Promise // 或任何其他构造函数 }
静态传值
<blog-post title="My journey with Vue"></blog-post>
动态赋值
<!-- 动态赋予一个变量的值 -->
<blog-post :title="post.title"></blog-post>
<!-- 动态赋予一个复杂表达式的值 -->
<blog-post :title="post.title + ' by ' + post.author.name"></blog-post>
父子组件传值
父组件
<template>
<h1>父组件</h1>
<Child1 :msg="msg"></Child1>
<Child2></Child2>
</template>
<script>
import Child1 from "./Child1.vue";
import Child2 from "./Child2.vue";
export default {
name: "Parent",
components: {
Child1,
Child2,
},
data() {
return {
msg: '你好',
}
},
}
</script>
<style scoped>
</style>
子组件
<template>
<h2>子组件1</h2>
<textarea>{{msg}}</textarea>
</template>
<script>
export default {
name: "Child1",
props: {
msg: String,
},
setup(props) {
console.log(props);
return props
}
}
</script>
<style scoped>
</style>
子组件向父组件传值
通过emit
子组件
<template>
<h2>子组件2</h2>
</template>
<script>
export default {
name: "Child2",
// setup(props, context) {
// context.emit('setShow', false);
// return {}
// },
setup(props, {emit}) {
emit('childEvent', "这是子组件传递过来的内容");
return {}
},
}
</script>
<style scoped>
</style>
父组件
<template>
<h1>传值测试</h1>
<Child1 :msg="msg"></Child1>
<Child2 @childEvent="parentEvent"></Child2>
<h2>{{name}}</h2>
</template>
<script>
import Child1 from "./Child1.vue";
import Child2 from "./Child2.vue";
import {ref} from "vue";
export default {
name: "Parent",
components: {
Child1,
Child2,
},
data() {
return {
msg: '你好',
name: "",
}
},
methods: {
parentEvent(value) {
this.name = value
}
}
}
</script>
<style scoped>
</style>
Vue Router
安装
cnpm install vue-router@4
新建Page1.vue
<template>
<h1>Page1</h1>
<p>{{ msg }}</p>
</template>
<script>
export default {
name: "Page1",
data() {
return {
msg: "Page组件"
}
}
}
</script>
<style scoped>
</style>
新建Page2.vue
<template>
<h1>Page2</h1>
<p>{{ msg }}</p>
</template>
<script>
export default {
name: "Page2",
data() {
return {
msg: "Page组件"
}
}
}
</script>
<style scoped>
</style>
在src
文件夹下新建router/index.ts
import {createRouter, createWebHashHistory} from "vue-router";
import page1 from '../components/Page1.vue';
import page2 from '../components/Page2.vue';
import Parent from "../components/Parent.vue";
// 定义routes路由的集合,数组类型
const routes = [
// 单个路由均为对象类型,path代表的是路径,component代表组件
{
path: '/',
redirect: '/index'
},
{
path: '/index',
name: 'index',
component: Parent
},
{
path: '/user/:name',
name: 'user',
component: Parent
},
{
path: '/page1',
name: 'page1',
component: page1
},
{
path: '/page2',
name: 'page2',
component: page2
},
]
// 实例化VueRouter并将routes添加进去
const router = createRouter({
history: createWebHashHistory(),
routes
})
// 抛出这个这个实例对象方便外部读取以及访问
export default router
修改App.vue
<template>
<h1>组件测试</h1>
<router-link to="/page1">Page1</router-link>
<router-link to="/page2">Page2</router-link>
<br/>
<router-link :to="{ name: 'user', params: { name: 'LiMing' }}">
Param传参
</router-link>
<br/>
<router-link :to="{ name: 'index', query: { name: 'LiMing' }}">
Query传参
</router-link>
<router-view></router-view>
<!-- <Parent>-->
<!-- </Parent>-->
</template>
<script lang="ts">
import Parent from "./components/Parent.vue";
export default {
name: "App",
components: {Parent}
}
</script>
<style>
</style>
修改main.ts
import {createApp} from "vue";
import App from "./App.vue";
import router from "./router/index";
const app = createApp(App)
// 一定要注入到vue的实例对象上
app.use(router)
app.mount('#app')
export default app
Vuex
Vuex 是 Vue .js 应用程序的状态管理模式 + 库。它充当应用程序中所有组件的集中存储,其规则确保状态只能以可预测的方式发生变异。
安装
cnpm install vuex@next --save
在src
文件夹下新建stroe/index.ts
import Vuex from 'vuex';
const store = new Vuex.Store({
state: {
// 定义一个name,以供全局使用
name: '张三',
// 定义一个number,以供全局使用
number: 0,
// 定义一个list,以供全局使用
list: [
{id: 1, name: '111'},
{id: 2, name: '222'},
{id: 3, name: '333'},
]
},
});
export default store;
修改main.ts
import {createApp} from "vue";
import App from "./App.vue";
import router from "./router/index";
import store from "./store/index";
const app = createApp(App)
// 一定要注入到vue的实例对象上
app.use(router)
app.use(store)
app.mount('#app')
export default app
修改Page1.vue
<template>
<h1>Page1</h1>
<p>{{ msg }}</p>
<button v-on:click="logStore">打印store变量</button>
</template>
<script>
export default {
name: "Page1",
data() {
return {
msg: "Page组件"
}
},
methods:{
logStore(){
alert(this.$store.state.name)
alert(this.$store.state.number)
alert(this.$store.state.list)
}
}
}
</script>
<style scoped>
</style>
官方建议把this.$store.state.XXX
最好放在计算属性中,使代码优雅
<template>
<h1>Page1</h1>
<p>{{ msg }}</p>
<button v-on:click="logStore">打印store变量</button>
</template>
<script>
export default {
name: "Page1",
data() {
return {
msg: "Page组件"
}
},
methods: {
logStore() {
alert(this.getName)
}
},
computed: {
getName() {
return this.$store.state.name
}
}
}
</script>
<style scoped>
</style>
使用mapState
解构
<template>
<h1>Page1</h1>
<p>{{ msg }}</p>
<button v-on:click="logStore">打印store变量</button>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: "Page1",
data() {
return {
msg: "Page组件"
}
},
methods: {
logStore() {
alert(this.name)
}
},
computed: {
...mapState(['name']),
}
}
</script>
<style scoped>
</style>
修改器
import Vuex from 'vuex';
const store = new Vuex.Store({
state: {
// 定义一个name,以供全局使用
name: '张三',
// 定义一个number,以供全局使用
number: 0,
// 定义一个list,以供全局使用
list: [
{id: 1, name: '111'},
{id: 2, name: '222'},
{id: 3, name: '333'},
]
},
// 在store对象中增加getters属性
getters: {
getName(state) { // 获取修饰后的name,第一个参数state为必要参数,必须写在形参上
return `hello${state.name}`;
}
},
});
export default store;
Page1.vue
<template>
<h1>Page1</h1>
<p>{{ msg }}</p>
<button v-on:click="logStore">打印store变量</button>
</template>
<script>
import { mapState } from 'vuex';
import {mapGetters} from "vuex";
export default {
name: "Page1",
data() {
return {
msg: "Page组件"
}
},
methods: {
logStore() {
alert(this.name)
alert(this.getName)
}
},
computed: {
...mapState(['name']),
...mapGetters(['getName']),
}
}
</script>
<style scoped>
</style>
修改Store的值
import Vuex from 'vuex';
const store = new Vuex.Store({
state: {
// 定义一个name,以供全局使用
name: '张三',
// 定义一个number,以供全局使用
number: 0,
// 定义一个list,以供全局使用
list: [
{id: 1, name: '111'},
{id: 2, name: '222'},
{id: 3, name: '333'},
]
},
// 在store对象中增加getters属性
getters: {
getName(state) { // 获取修饰后的name,第一个参数state为必要参数,必须写在形参上
return `hello${state.name}`;
}
},
mutations: {
setNumber(state) {
state.number = 5;
},
setNumberIsWhat(state, number) { // 增加一个带参数的mutations方法
state.number = number;
},
},
});
export default store;
Mutations里面的函数必须是同步操作,不能包含异步操作!
Page1.vue
<template>
<h1>Page1</h1>
<p>{{ msg }}</p>
<button v-on:click="logStore">打印store变量</button>
</template>
<script>
import {mapMutations, mapState} from 'vuex';
export default {
name: "Page1",
data() {
return {
msg: "Page组件"
}
},
methods: {
logStore() {
this.setNumberIsWhat({number:666});
alert(this.number)
this.setNumber();
alert(this.number)
}
},
computed: {
...mapState(['number']),
...mapMutations(['setNumber']),
...mapMutations(['setNumberIsWhat']),
}
}
</script>
<style scoped>
</style>
参考文档:https://juejin.cn/post/6928468842377117709
Axios
官方文档:https://axios-http.com/zh/docs/intro
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
安装
cnpm install axios
这里以调用https://api.4gml.com/NeteaseMusic
接口获取网易云热评为例
在src
目录下新建utils/request.ts
import axios from 'axios'
// 让请求在浏览器中允许跨域携带cookie
axios.defaults.withCredentials = true;
// 使用自定义配置新建一个实例
const instance = axios.create({
// url = base url + request url
baseURL: 'https://api.4gml.com',
// 设置超时时间 5s
timeout: 5000,
headers: {'X-Custom-Header': 'foobar'}
});
// 请求拦截器
instance.interceptors.request.use(
config => {
// 在发送请求之前做些什么
return config;
}, error => {
// 对请求错误做些什么
return Promise.reject(error);
}
)
// 响应拦截器
instance.interceptors.response.use(
response => {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
},
error => {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
}
)
export default instance
在src
目录下新建api
目录,在api
目录下新建music.ts
import request from "../utils/request.ts";
export const getMusicReview = () => {
return request({
url: '/NeteaseMusic',
method: 'get',
})
}
修改Page2.vue
<template>
<h1>Page2</h1>
<p>{{ msg }}</p>
<textarea class="tex" v-model="review"></textarea>
<button v-on:click="getReview">获取评论</button>
</template>
<script>
import {getMusicReview} from "../api/music.ts";
export default {
name: "Page2",
data() {
return {
msg: "Page组件",
review: "",
}
},
methods: {
getReview() {
getMusicReview()
.then(res => {
// alert(res.data.content)
this.review = res.data.content
})
.catch(res => {
alert("网络开小差了,没有获取到图片验证码哦");
})
}
}
}
</script>
<style scoped>
.tex{
height: 100px;
width: 300px;
}
</style>
防抖和节流
Vue3
没有内置支持防抖和节流,但可以使用 Lodash
等库来实现。
cnpm i --save lodash
修改Child2.vue
<template>
<h2>子组件2</h2>
<button @click="debouncedClick">防抖</button>
</template>
<script>
import _ from "lodash";
export default {
name: "Child2",
created() {
// 使用 Lodash 实现防抖
this.debouncedClick = _.debounce(this.click, 500)
},
unmounted() {
// 移除组件时,取消定时器
this.debouncedClick.cancel()
},
methods: {
click() {
console.log("点击")
}
},
setup(props, {emit}) {
emit('childEvent', "这是子组件传递过来的内容");
return {}
},
}
</script>
<style scoped>
</style>
注:@click中对应得是防抖封装后的函数名,而不是Method中的函数名!!!
参考文档:https://blog.csdn.net/zheng_jia_jun/article/details/114577857
Cookie
cnpm i js-cookie
创建
//创建简单的cookie
Cookies.set('name', 'value');
//创建有效期为7天的cookie
Cookies.set('name', 'value', { expires: 7 });
//为当前页创建有效期7天的cookie
Cookies.set('name', 'value', { expires: 7, path: '' });
取值
Cookies.get('name'); // => 'value'
Cookies.get('nothing'); // => undefined
//获取所有cookie
Cookies.get(); // => { name: 'value' }
删除值
Cookies.remove('name');
//如果值设置了路径,那么不能用简单的delete方法删除值,需要在delete时指定路径
Cookies.set('name', 'value', { path: '' });
Cookies.remove('name'); // 删除失败
Cookies.remove('name', { path: '' }); // 删除成功
//注意,删除不存在的cookie不会报错也不会有返回
参考文档:https://www.npmjs.com/package/js-cookie
localStorage
Vue
中使用localStorage
作为本地存储,解决了 cookie
存储空间不足的问题(cookie中每条cookie的存储空间为4k,localStorage中一般浏览器支持的是5M大小)。
创建
localStorage.setItem('userName', '张三');
localStorage.password = '123456';
读取数据
localStorage.getItem('userName');
localStorage.password
删除数据
localStorage.removeItem('userName')
参考文档:https://blog.csdn.net/zhanduo0118/article/details/110060623
懒加载
cnpm install vue3-lazy -S
用法
主要.js:
import { createApp } from 'vue'
import App from './app'
import lazyPlugin from 'vue3-lazy'
const app = createApp(App)
lazyPlugin.install(app, {
loading: 'loading.png',
error: 'error.png'
})
app.mount('#app')
模板:
<ul>
<li v-for="img in list">
<img v-lazy="img.src" >
</li>
</ul>
懒惰选项
钥匙 | 描述 | 违约 | 选项 |
---|---|---|---|
error | 加载失败时图像的 src | 'data-src' | String |
loading | 加载时图像的 src | 'data-src' | String |
参考文档:https://www.npmjs.com/package/vue3-lazy
一些错误
import path from ‘path’ 异常
path 模块是 Node.js 的东西,需要安装 Node.js 的声明文件
npm i @types/node -D
views 和 components有什么区别?
components
是小组件(可被views
组件复用)containers
是容器级组件(根据项目大小决定是否使用)views
是页面级组件(一般不被复用)
如何为每个界面设置Title
法一
const routes = [
{
path: '/index',
name: 'index',
component: Index,
meta: {
title:"这是动态title",
keepAlive: true, // 需要被缓存
content: 'disable',
}
},
]
router.beforeEach((to,from,next) => {
// 路由发生变化修改页面title
if (to.meta.title) {
document.title = to.meta.title;
}
next()
})
法二
<template>
<h1>主页</h1>
</template>
<script>
export default {
name: "index",
mounted() {
document.title = '需要设置的值';
}
}
</script>
<style scoped>
</style>