Vue3:基础学习笔记
点击跳转到Vue.js学习参考文档
文章目录
- vue3.0介绍
- 什么是Vue.js
- 安装
- vite构建工具工具创建vue3项目
- 使用npm创建
- 使用yarn
- vue3项目结构
- Vue声明式语法与数据双向绑定
- 命令式
- 声明式
- 数据双向绑定
- 模板语法
- 双括号语法
- v-once
- v-html
- v-bind
- 模板语法中使用JavaScript表达式
- 动态指令
- 计算属性
- watch监听数据的变化
- 类的多种绑定方式
- 放置字符串
- 放置对象
- 放置数组
- 数组和对象的结合
- Style样式的多种绑定方式
- 放置字符串
- 放置对象
- 放置数组
- v-if 和 v-show
- v-for循环
- 事件与参数、时间修饰符
- 事件修饰符
- 按键修饰符
- 系统修饰符
- 鼠标修饰符
- 表单输入双向绑定、修饰符
- 文本框 text
- 多行文本框textarea
- 复选框checkbox
- 单选框radio
- 选项框 select
- 数据绑定v-model的修饰符
- .lazy
- .number
- .trim
- 组件
- 父组件向子组件传递数据props
- 通过provide和inject 将数据提供给子组件
- 子组件向父组件传递数据:自定义事件
- Vue3生命周期
- beforeCreate()和created()
- beforeMount()和mounted()
- beforeUpdate()和updated()
- beforeUnmount()和unmounted()
- 合成API:Composition API
- Composition API :单个值ref
- Composition API :函数
- Composition API :对象 reactive({})
- Composition API :监听数据变化
- watchEffect
- watch
- setup详解
- 使用setup接收父组件数据
- 生命周期
- Vue3路由:vue-router
- 路由的基本使用
- 动态路由
- 路由正则与重复参数
- 嵌套路由
- 程序化导航:使用js跳转页面
- 导航到其他位置
- 替换当前位置
- 替换当前位置
- 命名路由与重定向和别名
- 命名路由
- 重定向:redirect
- 别名:alias
- 路由模式
- 哈希模式
- HTML5模式
- 导航守卫
- router.beforeEach
- router.beforeResolve
- beforeEnter
- 组件内防护
- 状态管理
- 通过reactive响应式对象管理
- Vuex状态管理
- map辅助函数
- vue3 实现前后端交互
- 通过fetch()
- 通过axios()
- vite 配置跨域请求
- Mock.js 模拟获取数据
- vue脚手架cli的使用
- 模块化管理 vuex
- 命名空间
- 模块中辅助函数的写法
vue3.0介绍
什么是Vue.js
1、前端开发框架
2、用于构建用户界面的渐进式框架
3、简化复杂的开发过程
4、Vue 也完全有能力为复杂的单页应用程序提供支持
安装
将 Vue.js 添加到项目中有四种主要方法:
1、在页面上将其导入为CDN包
<script src="https://unpkg.com/vue@next"></script>
2、下载 JavaScript 文件并自行托管
如果您想避免使用构建工具但不能在生产中使用 CDN,那么您可以下载相关.js文件并使用您自己的 Web 服务器托管它。然后您可以使用
3、使用npm安装
npm 是使用 Vue 构建大型应用程序时推荐的安装方法
4、使用官方CLI构建项目,该项目为现代前端工作流程(例如,热重载、lint-on-save 等)提供包含电池的构建设置
Vue 提供官方 CLI (打开新窗口)用于快速搭建雄心勃勃的单页应用程序
vite构建工具工具创建vue3项目
使用npm创建
前提:安装Node.js
步骤如下:
$ npm init vite@latest <project-name> 或者 $ npm init vite-app <project-name>$ cd <project-name>
$ npm install
$ npm run dev
使用yarn
$ yarn create vite <project-name> --template vue
$ cd <project-name>
$ yarn
$ yarn dev
vue3项目结构
Vue声明式语法与数据双向绑定
命令式
document.querySelector('h1').innerHTML="小范宝贝"
声明式
export default {name: "App",data(){return{msg:'小范同学'}},methods:{changeMsg(){this.msg = '小范美女'}}
};
数据双向绑定
数据变了,页面内容也会变,页面内容变了,数据也随之改变
<h1 @click="changeMsg">{{msg}}</h1><input type="text" v-model="msg" />
模板语法
双括号语法
<h1>{{msg}}</h1>
v-once
一次性插值,只渲染一次
<!-- v-once指令,使得内容只渲染一次 --><h1 @click="changeMsg" v-once>{{msg}}</h1>
v-html
在内容中插入HTML代码
<!--v-html指令 使得内容插入html的代码 --><div>{{content}}</div><div v-html="content"></div>
v-bind
绑定属性的内容
<!-- v-bind指令 绑定属性的内容 --><div v-bind:id="id"></div>
模板语法中使用JavaScript表达式
<template><div><!-- JavaScript可以在模板语法中使用 --><!-- 双括号语法 --><h1>{{ msg }}</h1><!-- split()分割msg字符串,得到一个数字 --><h1>{{msg.split('')}}</h1><!-- reverse() 使得数组内容颠倒 --><h1>{{msg.split('').reverse()}}</h1><!-- join()使得数组内容合并成字符串 --><h1>{{msg.split('').reverse().join('')}}</h1><!-- 可以使用三元运算符 --><div>{{color=="green"?"开心":"难过"}}</div></div>
</template><script>
// 声明式
export default {name: "App",data() {return {msg: "Hello,Word!",color:"green"};},methods: {},
};
</script>
动态指令
指令对应的属性名称是可以修改的
<template><div><!-- 动态指令 --><div v-bind:[attrbuteName]="d1"></div><button @click="toggleColor">点击切换颜色</button></div>
</template><script>
// 声明式
export default {name: "App",data() {return {attrbuteName:"class",d1:'d1'};},methods: {toggleColor() {this.attrbuteName = "id";},},
};
</script><style>#d1{margin-left: 47%;width: 100px;height: 100px;background-color: yellow;}.d1{margin-left: 47%;width: 100px;height: 100px;background-color: blue;}
</style>
计算属性
- 简化代码
<template><div><!-- 原来的msg --><h1>{{msg}}</h1><!-- 运用JS语句颠倒msg --><h1>{{msg.split('').reverse().join('')}}</h1><!-- 使用计算属性颠倒msg --><h1>{{reverseMsg}}</h1></div>
</template><script>
// 声明式
export default {name: "App",data() {return {msg: 'Hello World'};},computed:{reverseMsg(){return this.msg.split('').reverse().join('')}},methods: {toggleColor() {this.attrbuteName = "id";},},
};
</script>
watch监听数据的变化
想要监听数据的变化,可以使用watch监听,里面写监听目标变量的函数,里面有两个参数,第一个参数是新值,第二个参数是旧值。
<template><div><!-- 原来的msg --><h1>{{msg}}</h1><input type="text" v-model="msg"></div>
</template><script>
// 声明式
export default {name: "App",data() {return {msg: 'Hello World'};},watch:{msg(newValue,oldValue){if(newValue.length<10){alert("输入的值太少了!!!")}}}};
</script>
类的多种绑定方式
放置字符串
<template><div><!-- 类class --><!-- 第一种写法,放置字符串 --><h1 v-bind:class = "msg">hello</h1></div>
</template><script>
// 声明式
export default {name: "App",data() {return {msg: 'Hello World'};},
};
</script>
放置对象
<template><div><!-- 类class --><!-- 放置对象 --><h1 v-bind:class="{active:isActive}">Hello</h1><button @click="toggleActive">切换样式</button></div>
</template><script>
// 声明式
export default {name: "App",data() {return {isActive: true};},methods:{toggleActive(){this.isActive=!this.isActive}}};
</script>
<style scoped>.active{background-color: yellow;}
</style>
放置数组
<template><div><!-- 类class --><!-- 放置数组 --><h1 :class="arr">Hello</h1><button @click="toggleActive">切换类</button></div>
</template><script>
// 声明式
export default {name: "App",data() {return {arr: ['swiper','active']};},methods:{toggleActive(){this.arr.pop()}}
};
</script>
数组和对象的结合
<template><div><!-- 类class --><!-- 数组和对象的结合 --><h1 :class="[className, {active:isActive}]">Hello</h1><button @click="toggleActive">切换类</button></div>
</template><script>
// 声明式
export default {name: "App",data() {return {className : "abc",isActive : true};},methods:{toggleActive(){this.className= "cba",this.isActive = !this.isActive}}};
</script>
<style scoped>
.active {background-color: yellow;
}
</style>
Style样式的多种绑定方式
放置字符串
<template><div><!-- 类class --><!-- 第一种写法:放置字符串 --><h1 :style="msg">Hello</h1></div>
</template><script>
// 声明式
export default {name: "App",data() {return {msg: "background:red;"};},
};
</script>
放置对象
<template><div><!-- 类class --><!-- 第一种写法:放置字符串 --><h1 :style="{background: 'purple'}">Hello</h1></div>
</template><script>
// 声明式
export default {name: "App",data() {return {};},
};
</script>
放置数组
<template><div><!-- 类class --><!-- 第一种写法:放置字符串 --><h1 :style="[styleObj,{boxSizing: 'border-box'}]">Hello</h1></div>
</template><script>
// 声明式
export default {name: "App",data() {return {styleObj:{background: "pink",border: '1px solid blue'}};},
};
</script>
v-if 和 v-show
v-if…v-else-if…v-else… 可以根据不同的条件显示多个内容,频繁切换的话,较为消耗性能
v-show 根据条件确定是否显示单个内容,不显示时,其实是将样式改为display: none 所以性能消耗较小
<template><div><!-- 设置多个内容切换显示 --><h1 v-if = "user == '超级VIP'"> 欢迎金主爸爸</h1><h1 v-else>充值使你更强大</h1><button @click="toggleUser">切换用户</button><!-- 设置一个内容切换显示 --><h1 v-show="isShow">只显示我一个</h1><button @click="toggleShow">切换</button></div>
</template><script>
// 声明式
export default {name: "App",data() {return {user:'超级VIP',isShow: true};},methods:{toggleUser(){this.user = "普通用户"},toggleShow:function(){this.isShow = !this.isShow}}
};
</script>
v-for循环
- 循环数组
- 循环数组里的对象
- 循环对象
<template><div><!-- 循环数组 --><ol><li v-for="(item, i) in news" :key="i">{{ item }}====>{{ i }}</li></ol><!-- 循环数组里的对象 --><ol><li v-for="(item, i) in news1" :key="i">{{ item.title }}==>{{ item.content }}===>{{ item.athor }}====>{{ i }}</li></ol><!-- 循环对象 --><ol><li v-for="(item, i) in athor" :key="i">{{ item }}====>{{ i }}</li></ol></div>
</template><script>
// 声明式
export default {name: "App",data() {return {news: ["11111", "222222", "333333"],news1: [{title: "我是标题1",content: "我是内容1",athor: "作者1",},{title: "我是标题2",content: "我是内容2",athor: "作者2",},],athor:{name:'lingLing',age: '18'}}},
};
</script>
事件与参数、时间修饰符
绑定事件使用 v-on(简写@)
- 绑定事件不需要参数
<h1 @click="addEvent">{{num}}</h1>
- 绑定事件,直接处理表达式
<h1 @click="num += 2">{{num}}</h1>
- 绑定事件,传递参数
<h1 @click=" addEvent1(20)">{{num}}</h1>
- 绑定事件。传递 $event事件对象和参数
<h1 @click=" addEvent1(20,$event)">{{num}}</h1>
- 一个事件绑定多个处理函数
<h1 :style="{background:color}" @click="addEvent1(20,$event),changeColor($event)">{{num}}</h1>
事件修饰符
- 阻止事件冒泡 .stop
- 阻止默认事件 .prevent
- 事件只触发一次 .once
<h1 @click.once=" addEvent1(20,$event)">{{num}}</h1>
按键修饰符
enter/tap.delete/esc/space/up/down/left/right
<input type="text" @keydown.enter="searchEvent">
系统修饰符
.ctrl/.alt/.shift/.meta
鼠标修饰符
.left/.right/.middle
<template><div><!-- 绑定事件,不需要参数 --><h1 @click="addEvent">{{num}}</h1><!-- 绑定事件,直接处理表达式 --><h1 @click="num += 2">{{num}}</h1><!-- 绑定事件,传递参数 --><h1 @click=" addEvent1(20)">{{num}}</h1><!--绑定事件。传递 $event事件对象和参数 --><h1 @click=" addEvent1(20,$event)">{{num}}</h1> <!-- 一个事件绑定多个处理函数 --><h1 :style="{background:color}" @click="addEvent1(20,$event),changeColor($event)">{{num}}</h1><!-- 事件修饰符 --><!-- 阻止事件冒泡 .stop阻止默认事件 .prevent事件只触发一次 .once--><h1 @click.once=" addEvent1(20,$event)">{{num}}</h1> <!-- 按键修饰符enter/tap.delete/esc/space/up/down/left/right系统修饰符.ctrl/.alt/.shift/.meta鼠标修饰符.left/.right/.middle--><input type="text" @keydown.enter="searchEvent"></div>
</template><script>
// 声明式
export default {name: "App",data() {return {num:0,color: 'red'}},methods:{addEvent:function(e){console.log(e)this.num += 2},addEvent1:function(number){this.num += number},addEvent2:function(number,event){this.num += number},changeColor:function(){this.color = 'pink'},searchEvent:function(){console.log("执行了搜索事件!!!")}}
};
</script>
表单输入双向绑定、修饰符
文本框 text
*单行本文框数据的双向绑定
<input v-model="searchKey" type="text" @keydown="searchEvent" />
多行文本框textarea
- 多行文本框的数据绑定
<textarea v-model="lineText" name="textarea" id="" cols="30" rows="10"></textarea>
复选框checkbox
- 复选框的数据绑定,获取的是是否选中的内容
<input type="checkbox" name="likes" v-model="fruits" value="柿子"><input type="checkbox" name="likes" v-model="fruits" value="香蕉"><input type="checkbox" name="likes" v-model="fruits" value="葡萄"><input type="checkbox" name="likes" v-model="fruits" value="苹果">
单选框radio
只能选一个值
<input type="radio" name="sex" value="man" v-model="picked">
<input type="radio" name="sex" value="woman" v-model="picked">
选项框 select
添加multiple属性可以选择多个选项
<select name="citys" v-model="citys" multiple ><option value="广州"></option><option value="上海"></option><option value="北京"></option><option value="成都"></option></select>
数据绑定v-model的修饰符
.lazy
input变为change事件改变值,焦点失焦后才改变
<input v-model.lazy="searchKey1" type="text" @keydown="searchEvent" />
.number
把输入值转换为数字类型
<input v-model.lazy.number="searchKey2" type="text" @keydown="searchEvent" />
.trim
去掉空格
<input v-model.lazy.trim="searchKey3" type="text" @keydown="searchEvent" />
案例代码
<template><div><!-- 单行本文框数据的双向绑定 --><input v-model="searchKey" type="text" @keydown="searchEvent" /><h1>{{ searchKey }}</h1><!-- 多行文本框的数据绑定 --><textarea v-model="lineText" name="textarea" id="" cols="30" rows="10"></textarea><h1>{{ lineText }}</h1><!-- 复选框的数据绑定,获取的是是否选中的内容--><input type="checkbox" name="like" v-model="checked" value="123"><h1>{{checked}}</h1><!-- 复选框多个值的情况 --><input type="checkbox" name="likes" v-model="fruits" value="柿子"><input type="checkbox" name="likes" v-model="fruits" value="香蕉"><input type="checkbox" name="likes" v-model="fruits" value="葡萄"><input type="checkbox" name="likes" v-model="fruits" value="苹果"><h1>{{fruits}}</h1><!-- 单选框的数据绑定 --><input type="radio" name="sex" value="man" v-model="picked"><input type="radio" name="sex" value="woman" v-model="picked"><h1>{{picked}}</h1><!-- 单选选项框的数据绑定 --><select name="city" v-model="city"><option value="广州"></option><option value="上海"></option><option value="北京"></option><option value="成都"></option></select><h1>{{city}}</h1><!-- 多选选项框的数据绑定 --><select name="citys" v-model="citys" multiple ><option value="广州"></option><option value="上海"></option><option value="北京"></option><option value="成都"></option></select><h1>{{citys}}</h1><!-- 表单获取的是是否选中的内容 --><input type="checkbox" name="like" v-model="checked1" true-value="喜欢" false-value="不喜欢"><h1>{{checked1}}</h1><!-- 修饰符 --><!-- .lazy/input变为change事件改变值,焦点失焦后才改变 --><input v-model.lazy="searchKey1" type="text" @keydown="searchEvent" /><h1>{{searchKey1}}</h1><!-- .number 把输入值转换为数字类型 --><input v-model.lazy.number="searchKey2" type="text" @keydown="searchEvent" /><h1>{{searchKey2}}</h1>、<input v-model.lazy.trim="searchKey3" type="text" @keydown="searchEvent" /><h1>{{searchKey3}}</h1></div>
</template><script>
// 声明式
export default {name: "App",data() {return {searchKey: "百度一下",lineText: "",checked: false,fruits:[],picked:'',city:'',citys:[],checked1:'',searchKey1: "百度一下",searchKey2:'转换为数字类型',searchKey3:'去掉空格'};},methods: {searchEvent: function () {console.log("执行了搜索事件!!!");},},
};
</script>
组件
父组件向子组件传递数据props
父组件数据newContent绑定在content ,子组件通过props接收父组件的数据
父组件 App.vue代码如下:
<template><div><!-- 父组件数据newContent绑定在content --><News :content = "newsContent"></News></div>
</template><script>
// 声明式
import News from './components/News.vue'
export default {name: "App",data() {return {newsContent:"23岁女星与男子开房被原配抓包!!!"};},methods: {},components:{News}
};
</script>
子组件 App.vue代码如下:
<template><div><h1>新闻内容是{{content}}</h1></div>
</template>
<script>
export default {// 子组件通过props接收父组件的数据props:["content"]
}
</script>
通过provide和inject 将数据提供给子组件
父组件通过provide()将数据提供出去,子组件通过inject()将数据注入进来
父组件代码:App.vue
<template><div><Student></Student></div>
</template><script>
import { reactive,provide} from "vue";
import Student from './components/Student.vue'
export default {name: "App",data() {return {};},setup() {const student = reactive({name: "小红",age: 18,grade: "初一",});// 将数据提供出去provide("stu", student);return { };},components:{Student},
};
</script>
子组件代码:Student.vue
<template><div><h1>userName:{{ name }}</h1><h1>age: {{ age }}</h1><h1>年级:{{grade}}</h1></div>
</template><script>
import { inject } from "vue";
export default {setup() {// 将父组件提供的数据注入进来const student = inject('stu')return {...student}},
};
</script>
运行截图如下
子组件向父组件传递数据:自定义事件
子组件触发自定义事件1,父组件监听自定义事件1,并将监听到的值给自定义事件2
App.vue代码如下:
<template><div><!-- 子组件将数据传递给父组件,监听到sendParentMsg被触发就会运行自定义事件sendChildMsg --><Login @sendParentMsg ="getChildMsg" ></Login><h1>从子元素获得的值:{{msg}}</h1></div>
</template> <script>
// 声明式
import Login from './components/Login.vue'
export default {name: "App",data() {return {msg:''};},methods: {getChildMsg:function(value){this.msg = value}},components:{Login}
};
</script>
Login.vue代码如下:
<template><div><input type="text" v-model="userName"><button @click="sendMsg">将数据提交给父组件</button></div>
</template><script>
export default {data(){return{userName:''}},methods:{sendMsg:function(){// 使用$emit(事件名称,发送的事件值)触发自定义事件 sendParentMsg()this.$emit("sendParentMsg",this.userName)}},
}
</script>
Vue3生命周期
beforeCreate()和created()
初始化数据之前和初始化数据之后,初始化页面时调用
beforeMount()和mounted()
挂载渲染之前和挂载渲染之后,初始化完成后开始渲染页面
beforeUpdate()和updated()
页面数据发生更改时调用
beforeUnmount()和unmounted()
页面数据不显示时不渲染,vue2调用的是 beforeDestroy()和destroyed()
合成API:Composition API
可以在setup函数中使用Composition AP
普通写法和合成API的写法执行顺序,合成API更加快速便捷,且有利于代码的维护
Composition API :单个值ref
导入ref
ref()是一个变量变成响应式的
import {ref} from 'vue'
<template><div><h1 @click="changeEvent">普通方式计数:{{count}}</h1><h1 @click="num+=10">使用合成API计数:{{num}}</h1></div>
</template><script>
import {ref} from 'vue'export default {name: "App",data() {return {count: 0};},setup(){const num = ref(0)return{num}},methods: {changeEvent() {this.count++},},};
</script>
Composition API :函数
<template><div><h1 @click="changeNum">使用合成API定义的函数计数:{{num}}</h1></div>
</template><script>
import {ref} from 'vue'export default {name: "App",data() {return {};},//合成APIsetup(){//实例化变量 numconst num = ref(0)function changeNum(){num.value += 10}//返回相关的变量和函数return{num,changeNum}},
};
</script>
Composition API :对象 reactive({})
- reactive({})使得一个对象变成响应式的
- …toRefs(对象名)是用于解构对象,调用对象属性时不需要带上对象名作为前缀
<template><div><!-- 合成API中对象的使用 --><h1>姓名:{{user.userName}}</h1><!-- 合成API中返回的是解构对象,调用时不用加对象名前缀 --><h1>年龄:{{age}}</h1><h1 @click="changeType">类型:{{type}}</h1></div>
</template><script>
import { reactive,toRefs} from "vue";
export default {name: "App",data() {return {};},setup() {// 定义对象const user = reactive({userName: "小米",age: 18,type: "小奶狗",});// 更改对象数据function changeType(){user.type = "超级帅!!!"}//...toRefs(user)是解构对象return { num, changeNum, user, ...toRefs(user),changeType};},
};
</script>
Composition API :监听数据变化
watchEffect
跟踪所使用到的数据的变化
导入
import { watchEffect} from "vue";
//只跟踪匿名函数里使用到的值typewatchEffect(()=>{console.log(user.type)console.log("user.type的值发生改变时触发")})
watch
跟踪指定属性
导入
import { watch} from "vue";
- 监听单个属性
// 单个监听watch(num,(newNum,oldNum)=>{console.log(newNum)console.log(oldNum)console.log("num的值发生改变时触发")})
- 监听多个属性
// 多个监听watch([num,user],(newNum,oldNum)=>{console.log(newNum)console.log(oldNum)console.log("值发生改变时触发")})
setup详解
使用setup接收父组件数据
需要依赖props接收数据,父组件先绑定数据,子组件通过props接收,在setup中可以通过props计算响应式内容
- content属性包含了父组件中传过来的内容
子组件的代码:
<template><div><h1>userName:{{userName}}</h1><h1>age: {{age}}</h1><!-- 通过props生成一句话 --><h1>description: {{description}}</h1></div>
</template><script>
import {ref} from 'vue'
export default {setup(props,content){// 使用setup接收props的数据,通过props计算响应式的内容const description = ref(props.userName+"年龄是"+props.age)console.log(content)return{description}},// 接收来自父组件绑定的数据props:['userName','age']
}
</script>
父组件代码:
<template><div><User :userName = "userName" :age= "age" class="abc"></User></div>
</template><script>
import { reactive,toRefs} from "vue";
import User from './components/User.vue'
export default {name: "App",data() {return {};},setup() {// 定义对象const user = reactive({userName: "小米",age: 18,type: "小奶狗"})//...toRefs(user)是解构对象return { user, ...toRefs(user)};},components:{User},
};
</script>
生命周期
- onBeforeMount 挂载渲染之前
- onMounted 挂载渲染之后
- onBeforeUpdate 更新之前
- onBeforeUnmount 更新之后
先导入
import {onBeforeMount,onMounted,onBeforeUpdate,onBeforeUnmount} from 'vue'
再运用
setup(){// 声明周期函数的应用onBeforeMount(()=>{console.log("onBeforeMount")})},
Vue3路由:vue-router
路由的基本使用
- 路由:单页面应用根据路径的变化显示不同的内容
- 在项目路径下安装路由
E:\vuejs\vue3Router01> npm install vue-router@next
HTML
App.vue代码:
<template><div><p><router-link to="/">Go to Home</router-link><router-link to="/about">Go to About</router-link></p><router-view></router-view></div>
</template>
<script>
export default {name: "App",
};
</script>
JS
index.js
import {createRouter,createWebHashHistory} from 'vue-router'const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }const routes = [{ path: '/', component: Home },{ path: '/about', component: About },
]const router = createRouter({history:createWebHashHistory(),routes,
})export default router
main.js
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'import router from './router'const app = createApp(App)// 使用路由
app.use(router)app.mount('#app')
动态路由
单页面应用中,根据路径的id显示不一样的内容
index.js
import {createRouter,createWebHashHistory} from 'vue-router'
//导入组件
import News from '../components/News.vue'
import NotFound from '../components/NotFound.vue'
//将组件加进路由里
const routes = [{path:'/news/:id',component: News},{path:'/:path(.*)',component: NotFound}
]const router = createRouter({history:createWebHashHistory(),routes,
})export default router
news.vue
<template><div><h1>新闻页{{$route.params.id}}</h1></div>
</template>
<script>
export default {mounted(){console.log(this.$route)}
}
</script>
NotFound.vue
<template><div><h1>找不到页面</h1></div>
</template>
路由正则与重复参数
- \d+: id必须是数字
- +: id至少有一个
- *: id可有可无可重复可多个
- ? : id可有可无,不可重复,不可多个
index.js
mport News from '../components/News.vue'
import Article from '../components/Article.vue'
import Film from '../components/Film.vue'
import Song from '../components/Song.vue'
import Vidio from '../components/Vidio.vue'
import NotFound from '../components/NotFound.vue'const routes = [{path:'/news/:id',component: News},// \d+: id必须是数字{path:'/article/:id(\\d+)',component: Article},// + : id至少有一个{path:'/film/:id+',component: Film},// * : id可有可无可重复可多个{path:'/song/:id*',component: Song},// ? : id可有可无,不可重复,不可多个{path:'/vidio/:id?',component: Vidio},
]
嵌套路由
某些应用程序的 UI 由嵌套多级深的组件组成。在这种情况下,一个 URL 的参数(id)不同,对应嵌套组件的结构也不同,主结构相同,嵌套结构不同
index.js关键代码如下:
import User from '../components/User.vue'
import Hengban from '../components/Hengban.vue'
import Shuban from '../components/Shuban.vue'const routes = [{path:'/user/',component: User,children:[{path:'hengban',component:Hengban},{path:'shuban',component:Shuban}]
},
]
User.vue
<template><div><h1>user页面</h1><router-view></router-view></div>
</template>
Hengban.vue
<template><div><h1>这是横版页面</h1></div>
</template>
Shuban.vue
<template><div><h1>这是竖版页面</h1></div>
</template>
竖版运行视图
程序化导航:使用js跳转页面
导航到其他位置
除了<router-link to="url">
用于创建用于声明性导航的锚标记之外,我们还可以使用路由器的实例方法以编程方式完成此操作。
- 参数可以是字符串路径
this.$router.push("/news/:id")
- 参数是具有path的对象
this.$router.push({path: '/news/:id'})
// 携带参数跳转
this.$router.push({path: '/news/123456'})
- 带参数的命名路由,让路由器构建路径
this.$router.push({name:'film',params:{id:123}})
- 带查询querry的路径
this.$router.push({path:'/vidio',query:{search:'弯弯作死'}})
替换当前位置
this.$router.replace({path: '/news/123456'})
替换当前位置
此方法采用单个整数作为参数,指示在历史堆栈中前进或后退的步数,类似于window.history.go(n)。
<button @click="$router.go(1)">前进</button>
<button @click="$router.go(-1)">后退</button>
命名路由与重定向和别名
命名路由
您可以拥有多个router-view
并为每个router-view命名,一个router-view
没有名字的将default作为它的名字。
App.vue关键代码
<router-view name="ShopTop"></router-view>
<router-view></router-view>
<router-view name="ShopFooter"></router-view>
index.js关键代码
import ShopMain from '../components/ShopMain.vue'
import ShopTop from '../components/ShopTop.vue'
import ShopFooter from '../components/ShopFooter.vue'{path: '/shop',components: {default:ShopMain,ShopTop:ShopTop,ShopFooter:ShopFooter}},
ShopMain.vue关键代码
<template><div><h1>ShopMain主要内容</h1></div>
</template>
ShopTop.vue关键代码
<template><div><h1>ShopTop头部组件</h1></div>
</template>
ShopFooter.vue关键代码
<template><div><h1>ShopFooter底部组件</h1></div>
</template>
重定向:redirect
- 重定向也在routes配置中完成。从/a到重定向/b:
const routes = [{ path: '/home', redirect: '/' }]
- 重定向还可以针对命名路由:
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]
- 重定向还可以使用一个函数进行动态重定向
就是说输入/mall路由就会跳转到/shop页面
const routes = [{path:'/mall',redirect:(shop)=>{return {path:'/shop'}}},
]
别名:alias
/shop的别名/home意味着当用户访问时/store,URL 仍然存在/store,但它会像用户正在访问一样匹配/shop。通过通过数组取多个别名
{path: '/shop',alias: '/store',components: {default:ShopMain,ShopTop:ShopTop,ShopFooter:ShopFooter}},
路由模式
哈希模式
使用哈希模式URL会出现一个 # ,URL 的这部分永远不会发送到服务器,所以它不需要在服务器级别进行任何特殊处理
import { createRouter, createWebHashHistory } from 'vue-router'const router = createRouter({history: createWebHashHistory(),routes: [//...],
})
HTML5模式
使用HTML5模式,URL 将看起来“正常”,请求会发送到服务器。所以需要配置适当的服务器
import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(),routes: [//...],
})
导航守卫
Vue router 提供的导航守卫主要用于通过重定向或取消导航来保护导航。有多种方法可以连接到路由导航过程:全局、每个路由或组件内。
router.beforeEach
全局导航前守卫
index.js
router.beforeEach((to, from,next) => {// ...// explicitly return false to cancel the navigationconsole.log(to)console.log(from)next()
})
从store页面跳转到page页
router.beforeResolve
全局保护,当路由跳转完成之后触发
router.beforeResolve(async to => {if (to.meta.requiresCamera) {try {await askForCameraPermission()} catch (error) {if (error instanceof NotAllowedError) {// ... handle the error and then cancel the navigationreturn false} else {// unexpected error, cancel the navigation and pass the error to the global handlerthrow error}}}
})
beforeEnter
单路由保护,进入路由前触发
{path: '/shop',alias: '/store',components: {default: ShopMain,ShopTop: ShopTop,ShopFooter: ShopFooter}},
从store页面跳转到page页
组件内防护
写在组件里面的
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
// 组件内导航防护beforeRouteEnter() {console.log("路由进入组件");},beforeRouteUpdate() {console.log("路由更新");},beforeRouteLeave() {console.log("路由离开");},
状态管理
通过reactive响应式对象管理
通过reactive响应式对象,再通过依赖provide和inject注入子组件中
index.js
import { reactive} from 'vue'// 状态管理仓库
const store = {state : reactive({message:"你好"}),setMessage(value){this.state.message = value;}
}
export default store
父组件:App.vue
import store from './store/index.js'
export default {provide:{store}
}
子组件:HelloWord.vue
inject:['store']
Vuex状态管理
home.vue
调用$store
<template><div class="home"><h1>商品数量:{{ $store.state.count }}</h1><h2>商品价格:100</h2><h1>商品总价:{{ $store.getters.totalPrice }}</h1><button @click="changeEvent">添加数量</button><h1>段子</h1><p v-for="(item,i) in $store.state.dzList" :key="i">{{item.text}}</p></div>
</template><script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";export default {name: "Home",components: {HelloWorld,},methods: {changeEvent: function () {// 触发状态的方法// 触发无参数的方法// this.$store.commit("setCount");// 触有参数的方法this.$store.commit("setCountNum", 3);},},mounted:function(){this.$store.dispatch('getDz')}
};
</script>
index.js
使用store
import { createStore } from 'vuex'// 管理全局所用到的数据
export default createStore({// 设置全局数据state: {count:0,dzList:[]},/*** 含计算属性的方法*/getters:{totalPrice:function(state){return state.count*100}},/*** 同步的方法* 修改状态的方法*/mutations: {// 无参数setCount:function(state){state.count++;},// 有参数setCountNum:function(state,num){state.count+=num;},setDzList:function(state,arr){state.dzList = arr;}},/*** 异步的方法* 使用Ajax请求修改数据*/actions: {getDz:function(context){// 开放免费的APIlet api = "https://api.apiopen.top/getJoke?page=1&count=10&type=text";// 发出请求fetch(api).then((res) => res.json()).then((result) => {console.log(result)context.commit('setDzList',result.result)});}},modules: {}
})
map辅助函数
- mapState
- mapGetters
- mapMutations
- mapActions
map映射可以使得数据调用更加方便,不用加上$store.state,可以直接使用变量名
组件Home.vue
import {mapState, mapGetters,mapMutations,mapActions} from 'vuex'export default {name: "Home",components: {HelloWorld,},/*** 把状态映射到组件上* 直接调用数据*/computed:{//映射数据...mapState(['count']),...mapState({productCount:(state)=>state.count}),//映射计算属性...mapGetters(['totalPrice'])},methods: {changeEvent: function () {this.$store.commit("setCountNum", 3);},//映射改变状态的方法...mapMutations(['setCountNum']),...mapActions(['getDz'])},mounted:function(){this.$store.dispatch('getDz')}
};
vue3 实现前后端交互
通过fetch()
关键代码段
// 获取数据显示到页面setup() {// 开放免费的APIlet api = "https://api.apiopen.top/getJoke?page=1&count=10&type=text";// 发出请求fetch(api).then((res) => res.json()).then((result) => {store.setDzList(result.result);console.log(result.result);});return {store};
通过axios()
终端安装axios:npm install axios --save
import axios from 'axios'// 获取数据显示到页面setup() {// 开放免费的APIlet api = "https://api.apiopen.top/getJoke?page=1&count=10&type=text";// 发出请求axios.get(api).then((result)=>{console.log(result)store.setDzList(result.data.result)// store.setDzList(result);})return {store};},
vite 配置跨域请求
跨域配置文件vite.config.js
/*** 跨域服务器的配置文件*/module.exports = {proxy :{'/api':{target: 'https://pvp.qq.com/',changeOrigin:true, //是否允许跨域rewrite: path => path.replace(/^\/api/,'')}}}
Mock.js 模拟获取数据
链接: 点击跳转到官网.
可以拦截 Ajax 请求,返回模拟的响应数据
index.js
import Mock from 'mockjs'
Mock.mock("/user/userinfo","get",(req,res)=>{console.log(req,res)return{username:"老陈",type:"帅!"}}
)
vue脚手架cli的使用
安装脚手架cli
npm install -g @vue/cli
查看版本
vue --version
创建项目
vue create vueproject01
选择版本
切换到项目路径
cd vueproject01
运行
npm run serve
模块化管理 vuex
在store中导入模块user,user1
import { createStore } from 'vuex'
import user from './user.js'
import user1 from './user1.js'// 管理全局所用到的数据
export default createStore({// 设置全局数据state: {...},getters:{...},mutations: {...},actions: {...},modules: {user,user1}
})
user模块,user.js代码如下:
/*** 用户模块*/const user = {state: () => ({username: "老陈",age: 30}),mutations: {setUsername:function(state){state.username = "小陈"},setAge:function(state){state.age = 40}},actions: {asyncSetAge:function(context){setTimeout(()=>{context.commit('setAge')},3000)}},getters: {description:function(state,getters,rootState){return state.username + '的年龄是' + state.age+'岁!'}}
}export default user
命名空间
作用:区分每个模块,以防每个模块的getters和actions肯定会出现同名的情况
const user = {// 命名空间namespaced: true,.....
export default user
路由中的渲染User.vue
要加上模块名
<!-- 命名空间的写法 --><h1>用户名:{{ $store.state.user1.username }}</h1><h1>年龄:{{ $store.state.user1.age }}</h1><h1>描述:{{ $store.getters["user1/description"] }}</h1><button @click="changeAge1">修改年龄</button>
模块中辅助函数的写法
<template>
<!-- 命名空间:辅助函数的写法 --><h1>用户名:{{ user1.username }}</h1><h1>年龄:{{ user1.age }}</h1><h1>描述:{{ description }}</h1><button @click=" setAge">异步修改年龄</button></div>
</template><script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {computed: {...mapState(["user1"]),...mapGetters("user1", ["description"]),...mapMutations('user1',['setAge'])},methods: {...mapActions("user1", ["asyncSetAge"]),},
};
</script>
Vue3:基础学习笔记相关推荐
- guido正式发布python年份_Python 基础学习笔记.docx
Python 基础学习笔记 基于<Python语言程序设计基础(第2版)> 第一部分 初识Python语言 第1章 程序设计基本方法 1.1 计算机的概念 计算机是根据指令操作数据的设备, ...
- ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步
http://blog.jobbole.com/85008/ ASP.Net MVC开发基础学习笔记(5):区域.模板页与WebAPI初步 2015/03/17 · IT技术 · .Net, Asp. ...
- Python3 基础学习笔记 C09【文件和异常】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- Python3 基础学习笔记 C08 【类】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- Python3 基础学习笔记 C07【函数】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- Python3 基础学习笔记 C06【用户输入和 while 循环】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- Python3 基础学习笔记 C05【字典】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- Python3 基础学习笔记 C04【if 语句】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- Python3 基础学习笔记 C03【操作列表】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- Python3 基础学习笔记 C02【列表】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
最新文章
- 软件测试质量过程检测文档_如何编写实际上有效的质量检查文档
- 北科院分子互作实战专题培训班(10月底/11月底班)(生物医药与营养健康协同创新中心)...
- mybatis的快速入门
- python读取json配置文件_Python简单读取json文件功能示例
- ubuntu系统安装python hello_ubuntu 下python安装及hello world
- 您使用的是不受支持的命令行标记: --unsafely-treat-insecure-origin-as-se
- 同一个JDK,命令行运行,与JNI加载虚拟机,还是有差异
- y=asin(wx+φ)的对称中心_y=asin(wx+φ)怎么求
- python时间序列进行线性插值_精解Python实现线性插值法——一看就会
- IT学习网站,各大主流网站
- 这几天加班熬夜把所有Python库整理了一遍,非常全面!
- 网络技术安全开发安卓APP
- vs+html教学,VS Code怎么运行html文件
- React ,Redux 教程汇总
- 岗位述职报告PPT怎么做?
- android 通讯录 编程,以编程方式批量添加数千个Android联系人
- GTMBase64的详细用法
- 对比Ubuntu与Win10的资源占用
- 如何彻底禁用笔记本电脑的键盘或者禁用笔记本的触控屏,及禁用后如何恢复,解决笔记本电脑蓝屏信息显示:“systern thread exception no handled” 失败操作“etd.sys
- Vue-学习笔记-06 v-if详解