Ⅰ vue-router
【一】 路由守卫
# 1 路由守卫是什么
是否登录,登录后才能访问,没登录重定向到login
作用:对路由进行权限控制
# 2 全局守卫、独享守卫、组件内守卫
- 使用
import Element from 'element-ui'
// 全局路由守卫-->前置 路由守卫
router.beforeEach((to, from, next) => {
// to: 要去的路由对象
// from:来自哪个路由对象
// next:跳转到某个路径
// 要去的路径,如果不是/login或 / 就要判断有没有登录【登录后token保存到localStorage中了】
if (to.name == 'login' || to.name == 'home') {
// 直接走
next()
} else {
//判断有没有登录
let token = localStorage. ('token')
console.log(token)
if (token) {
next()
} else {
// alert('您没有登录,请先登录')
Element.Message.error('您没有登录,请先登录') // router是个对象 不是组件 不能用$message
next({name: 'login'}) // 跳转到login
}
}
})
- 保存token到浏览器中
methods: {
handleLogin() {
// 发送ajax请求到后端-->post请求
axios.post('http://127.0.0.1:8000/login/', {
username: this.username,
password: this.password
}).then(res => {
if (res.data.code == 100) {
// 保存token到浏览器中
localStorage.setItem('token', res.data.token) // 保存token到浏览器中
//跳转到电影页面
this.$router.push('/films')
} else {
alert(res.data.msg)
}
}).catch(err => {
alert(err)
})
}
}
【二】路由两种工作模式
# 1 对于一个url来说,什么是hash值?—— # 及其后面的内容就是hash值
# 2 hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
# 3 hash模式:# 后面带路径
地址中永远带着 #号,不美观
若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
兼容性较好
# 4 history模式:
地址干净,美观 。
兼容性和hash模式相比略差。
应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题
# vue项目创建时会让你选择是否是history模式 就是解决 #号,不美观 问题
Ⅱ vue3介绍
【一】vue2和vue3不同
# 1 vue2的所有东西,vue3都兼容
# 2 vue3 不建议使用vue2的写法-->配置项API
# 3 vue3 :选项式 API 和组合式 API
-选项式:配置项:就是vue2的写法
export default{
data(){
return {}
},
methods:{}
}
-组合式 :
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
function add(){
}
- 选项式:配置项:就是vue2的写法
- 使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改 。
- 组合式 :就是vue3的写法
- 代码更加有序的组织在一起
【二】快速体验组合式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style></style>
</head>
<body>
<div id="app">
<p>{{count}}</p>
<br>
<button @click="handleAdd">点我加1</button>
</div>
</body>
<script>
let app=Vue.createApp({
setup() {
let count=Vue.ref(0)
let handleAdd=()=>{
count.value++
}
return {
count,
handleAdd
}
},
})
app.mount("#app")
</script>
</html>
【三】快速体验配置项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style></style>
</head>
<body>
<div id="app">
<p>{{count}}</p>
<br>
<button @click="handleAdd">点我加1</button>
</div>
</body>
<script>
let app=Vue.createApp({
data(){
return {
count:100
}
},
methods:{
handleAdd(){
this.count++
}
}
})
app.mount("#app")
</script>
</html>
【四】 拥抱ts
# 1 之前写vue2用js
# 2 vue3-->ts-->微软推出的-->最终还是要被编译成js才能运行在浏览器中
-使用ts写,可以避免很大错误
-ts是js的超集--->ts完全兼容js
# 3 我们现在学到的是
vue2+js+vue-router+vuex+elementui
vue3+js+vue-router+pinia+elementui-plus
# 4 变化
新的生命周期钩子
data 选项应始终被声明为一个函数
移除keyCode支持作为 v-on 的修饰符
Ⅲ vue3快速创建项目
【一】使用vue-cli创建
# 跟之前几乎一样
或者是 不用管理员 运行终端 在终端上打 C:\Users\zhangyubin>vue ui 进行创建 只不过步骤一样 只是可视化界面
【二】使用vite创建(推荐)
- 网址:https://vitejs.cn/
- 步骤
#1 什么是vite?—— 新一代前端构建工具。
优势如下:
开发环境中,无需打包操作,可快速的冷启动。
轻量快速的热重载(HMR)。
真正的按需编译,不再等待整个应用编译完成。
# 2 兼容性注意
Vite 需要 Node.js 版本 18+,20+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本
官网:https://cn.vitejs.dev/
# 3 创建工程
# 不指定名字创建:npm create vite@latest
# 配置npm镜像站:npm config set registry https://registry.npmmirror.com
# 查看镜像站:npm config get registry
# 指定名字创建
# 创建项目方式一
npm create vite@latest
# 创建项目方式二:指定名字
npm create vite@latest vue3_demo002
# 创建项目方式三
cnpm create vite@latest vue3_demo002
# 创建项目方式四
cnpm create vite vue3_demo002
# 3 使用编辑器打开vue3项目
# 4 安装依赖
npm install
# 5 运行项目
npm run dev
- 创建项目贼快,是因为没有创建依赖 需要打开项目之后 手动创建依赖 npm install
- vue3的启动配置项还是一样
- vite创建配置项不一样
【三】运行vue项目时,执行的命名
#1 运行vue项目时,执行的命名
# npm run serve
# npm run dev
# 2 对应的是package.json中
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
【四】目录结构(vite)
Ⅳ 常用api
【一】 定义变量统一用const
# 1 const是常量-->不允许变的
# 2 用 ref包裹后,是个对象,虽然对象是常量,对象不能变,对象.value可以变化
# 3 之所以定义成const原因是,后期不能修改对象 【对象.value可以改】
# 4 如果用let声明 ,后期修改对象不会报错,导致程序出问题
【二】以后代码都写在setup函数中-->组合式
# 组合式和配置项能不能混用?
-可以混用
-并且在配置项api的方法中,可以拿到setup函数中定义的变量
-以后只用一种
-配置项
-组合式(推荐的)
【三】setup函数
# 1 如果使用配置项API--->写起来跟vue2一样
# 2 如果写组合式API--->所有代码都要写在setup函数中
-后期除了setup函数,其他都不带了
# 3 setup函数必须返回变量或函数-->在template中才能使用
# 4 默认不带响应式,需要使用ref或reactive包裹
<template>
<div class="about">
<h1>vue3的组合式写法</h1>
{{name}}今日功德+{{count}}
<button @click="add">功德+1</button>
<button @click="handlerChangName">切换收益人</button>
</div>
</template>
<script>
import {ref,reactive} from "vue";
export default {
name:'AboutView.vue',
setup(){
//做成响应式,必须使用 Vue3提供的类,包裹 ref reactive
// let count=0
const count=ref(0)
function add(){
// count+=1
console.log(typeof (count)) // console.log(typeof (count)) --> object
// count 是 ref 的对象
count.value+=1 // 从对象中取出具体的值 +1
console.log(count.value)
}
// 点击按钮,切换名字
const name=ref('zyb')
const handlerChangName=()=>{
name.value='hjj'
count.value=0
}
return {count,add,name,handlerChangName}
}
}
</script>
【四】ref
# 1 ref 包裹值类型[数字,字符串,布尔],做成响应式
# 2 reactive包裹引用类型[对象,数组],做成响应式
# 3 使用reactive包裹的对象,直接通过 . [] 取值赋值就是响应式
ref包裹的对象,需要使用 对象.value 修改值
# 4 使用ref包裹的,在template中,不许用使用 变量.value
# 用于包裹 值 【数字,字符串,布尔】类型变量,使其具有响应式的类
const count = ref(0)
count.value
【五】 reactive
# 用于包裹 引用 【数组,对象】类型变量,使其具有响应式的类
// 使用reactive包裹 对象,数组
const user_detail=reactive({name:'zyb',age:18})
function addage(){
user_detail.age++
console.log(user_detail.age)
}
# 使用时,不需要 对象.value-->因为它是个代理对象
user_detail.age++
【六】计算属性
<template>
<div class="about">
<h1>vue3的组合式写法</h1>
<p>姓:<input type="text" v-model="person.firstName"></p>
<p>名:<input type="text" v-model="person.lastName"></p>
{{ person }}
<br>
<!-- <p>您的全名是:{{person.fullName}}</p>-->
<p>您的全名是:<input type="text" v-model="person.fullName"></p>
</div>
</template>
<script>
import {computed} from "vue";
export default {
name:'AboutView.vue',
setup(){
// 计算属性-->页面中输入用户名字:firstName和lastName-->使用计算属性-->fullName
const person = reactive({
firstName: '',
lastName: ''
})
// firstName 和 lastName 变-->fullName会变
// person.fullName = computed(() => {
// return person.firstName + person.lastName
// })
// fullName变 firstName和 lastName 也变
person.fullName = computed({
get() { // 修改firstName 或lastName 会触发
return person.firstName + person.lastName
},
set(value) { //修改fullName 会触发这里,被修改后的值放这里
person.firstName = value.slice(0, 1)
person.lastName = value.slice(1)
}
})
return {person}
}
}
</script>
【七】监听属性
【1】监听值类型,监听对象类型,监听多个变量
(1)监听值类型
# js
const height =ref(180)
function handlerAddHeight(){
height.value++
}
// 监听值类型变化
watch(height, (newValue, oldValue) => {
console.log('height变化了', newValue, oldValue)
})
# template
<p>你的身高:{{height}}</p>
<button @click="handlerAddHeight">点击身体增加一厘米,你兄弟会失去点什么</button>
(2)监听对象类型
# js
// 监听对象类型
const p = reactive({name: 'zyb', age: 19})
function changeName() {
p.name = '哆啦梦'
}
watch(() => p.name, (newValue, oldValue) => {
console.log('p.name变化了', newValue, oldValue)
})
# template
<p>姓名是:{{ p.name }},年龄是:{{ p.age }}</p>
<button @click="changeName">变名字</button>
(3)监听多个变量
# js
// 监听多个变化-->每个发生变化,都会触发
const sum = ref(100)
const msg = ref('很好')
function changeValue(){
sum.value++
msg.value='不太好'
}
watch([sum, msg], (newValue, oldValue) => {
console.log('sum或msg变化了', newValue, oldValue)
})
# template
{{ sum }}==={{ msg }}
<button @click="changeValue">变</button>
【2】watchEffect函数
# watchEffect 使用:不用指定监听谁,只要watchEffect内部用了某个变量,某个变量发送变化,就会触发
# 如果两个同时都变化,只会执行一次
watchEffect(() => {
const x1 = sum.value
const x2 = person.name
console.log('watchEffect配置的回调执行了')
})
# js
// watchEffect
const q = reactive({name: 'zyb', age: 19})
const gg = ref(15)
function change(){
gg.value++
q.name='htt'
}
watchEffect(() => {
const x1 = gg.value
const x2 = q.name
console.log(x1)
console.log(x2)
console.log('watchEffect配置的回调执行了')
})
# template
<button @click="change">变化</button>
【八】总的代码
<template>
<div class="about">
<h1>vue3的组合式写法</h1>
{{name}}今日功德+{{count}}
<button @click="add">功德+1</button>
<button @click="handlerChangName">切换收益人</button>
<hr>
<p>用户名:{{user_detail.name}}</p>
<p>年龄:{{user_detail.age}}</p>
<button @click="addage">点击增加年龄</button>
<hr>
<p>姓:<input type="text" v-model="person.firstName"></p>
<p>名:<input type="text" v-model="person.lastName"></p>
{{ person }}
<br>
<!-- <p>您的全名是:{{person.fullName}}</p>-->
<p>您的全名是:<input type="text" v-model="person.fullName"></p>
<hr>
<p>你的身高:{{height}}</p>
<button @click="handlerAddHeight">点击身体增加一厘米,你兄弟会失去点什么</button>
<p>姓名是:{{ p.name }},年龄是:{{ p.age }}</p>
<button @click="changeName">变名字</button>
{{ sum }}==={{ msg }}
<button @click="changeValue">变</button>
<hr>
<button @click="change">变化</button>
</div>
</template>
<script>
import {ref,reactive,computed,watch,watchEffect} from "vue";
export default {
name:'AboutView.vue',
setup(){
//做成响应式,必须使用 Vue3提供的类,包裹 ref reactive
// let count=0
const count=ref(0)
function add(){
// count+=1
console.log(typeof (count)) // console.log(typeof (count)) --> object
// count 是 ref 的对象
count.value+=1 // 从对象中取出具体的值 +1
console.log(count.value)
}
// 点击按钮,切换名字
const name=ref('zyb')
const handlerChangName=()=>{
name.value='hjj'
count.value=0
}
// 使用reactive包裹 对象,数组
const user_detail=reactive({name:'zyb',age:18})
function addage(){
user_detail.age++
console.log(user_detail.age)
}
// 计算属性-->页面中输入用户名字:firstName和lastName-->使用计算属性-->fullName
const person = reactive({
firstName: '',
lastName: ''
})
// firstName 和 lastName 变-->fullName会变
// person.fullName = computed(() => {
// return person.firstName + person.lastName
// })
// fullName变 firstName和 lastName 也变
person.fullName = computed({
get() { // 修改firstName 或lastName 会触发
return person.firstName + person.lastName
},
set(value) { //修改fullName 会触发这里,被修改后的值放这里
person.firstName = value.slice(0, 1)
person.lastName = value.slice(1)
}
})
const height =ref(180)
function handlerAddHeight(){
height.value++
}
// 1 监听值类型变化
watch(height, (newValue, oldValue) => {
console.log('height变化了', newValue, oldValue)
})
// 2 监听对象类型
const p = reactive({name: 'zyb', age: 19})
function changeName() {
p.name = '哆啦梦'
}
watch(() => p.name, (newValue, oldValue) => {
console.log('p.name变化了', newValue, oldValue)
})
// 3 监听多个变化--》每个发生变化,都会触发
const sum = ref(100)
const msg = ref('很好')
function changeValue(){
sum.value++
msg.value='不太好'
}
watch([sum, msg], (newValue, oldValue) => {
console.log('sum或msg变化了', newValue, oldValue)
})
// watchEffect
const q = reactive({name: 'zyb', age: 19})
const gg = ref(15)
function change(){
gg.value++
q.name='htt'
}
watchEffect(() => {
const x1 = gg.value
const x2 = q.name
console.log(x1)
console.log(x2)
console.log('watchEffect配置的回调执行了')
})
return {count,add,name,handlerChangName,user_detail,addage,person,height,handlerAddHeight,
p,changeName,sum,msg,changeValue,change}
}
}
</script>
- 有的代码也可以自用,只要不返回出去 template 就不能展示
let a = 10
a++
console.log(a)
function demo(a, b) {
return a + b
}
let res = demo(a, 11)
console.log(res)
Ⅴ 生命周期
# vue2中8个生命周期钩子
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
# vue3中8个生命周期钩子--->配置项API
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeUnmount
unmounted
# vue3 组合式api的生命周期钩子
beforeCreate===>setup()
created=======>setup()
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted
【一】vue3的配置项api生命周期钩子
export default {
name: 'HomeView',
beforeCreate() {
console.log('beforeCreate')
},
created() {
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
},
beforeUpdate() {
},
updated() {
},
beforeUnmount() {
},
unmounted() {
console.log('unmounted')
}
}
【二】vue3的组合式生命周期钩子
<template>
<h1>生命周期钩子--配置项</h1>
{{name}}
<button @click="changeName">点我变化值</button>
</template>
<script>
import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'
export default {
name: 'HomeView',
setup() {
// 组合式api写法
// 1 组件还没有创建时候执行:beforeCreate
console.log('beforeCreate')
// 2 组件创建完成执行:created-->跟后端交互拿数据
const name=ref('zyb')
// axios.get().then(res=>{
// name=res.data.name
// })
function changeName(){
name.value='胡图图'
}
console.log('created')
//3 beforeMount-->onBeforeMount
// onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted
onBeforeMount(()=>{
console.log('onBeforeMount','组件挂载前')
})
//4 mounted-->onMounted
onMounted(()=>{
console.log('onMounted','组件挂载后')
})
//5 beforeUpdate-->onBeforeUpdate
onBeforeUpdate(()=>{
console.log('onBeforeUpdate','更新之前')
})
//6 updated-->onUpdated
onUpdated(()=>{
console.log('onUpdated','更新之后')
console.log(name.value)
})
//7 beforeUnmount-->onBeforeUnmount
onBeforeUnmount(()=>{
console.log('onBeforeUnmount','销毁之前')
})
//8 unmounted-->onUnmounted
onUnmounted(()=>{
console.log('onUnmounted','销毁后')
})
return {changeName,name}
}
}
</script>
Ⅵ setup的特殊写法
# 1 vue3中之前写组合式的组件写法
export default {
name: 'HomeView',
setup() {
}
}
####重点####
# 1 组件,只需要导入,就会自动注册,必须带后缀名 vue
# 2 setup写法
<script setup> 写原来setup函数中的代码即可</script>
# 3 生命周期钩子--beforeCreate,created,on。。。。
# 4 监听属性,计算属性
# 5 组件间通信 父传子
# 父组件中:跟之前一样
<HelloWorld :msg="msg"></HelloWorld>
# 子组件中: defineProps 固定写法
defineProps({
msg: String,
})
# 6 组件通信,子传父
-父组件中:
# html
<HelloWorld @send="handleReceive"></HelloWorld>
<p>父组件中得name:{{name}}</p>
# js
<script setup>
const name = ref('')
function handleReceive(a){
name.value=a
}
</script>
-子组件中:
# js // defineEmits等同于之前的 this.$emit
let $emit = defineEmits(['send']) # 等同于之前的 this.$emit
const name =ref('')
const handleSend=()=>{
$emit('send',name.value)
}
# html
<input type="text" v-model="name">-->{{name}}
<br>
<button @click="handleSend">点我传给父亲</button>
# 7 插槽
# 8 mixin 没了-->直接导入导出用
# 9 插件一样
# 10 toRefs-->把对象中所有变量都做成响应式
# 11 toRef -->只把对象中某一个做成响应式
# 12 ref属性
【一】setup写法 < script setup >
<template>
<h1>setup的特殊写法</h1>
{{name}}
<button @click="changeName">变名字</button>
</template>
<script setup>
import {ref} from 'vue'
const name = ref('name')
function changeName() {
name.value = '胡图图'
}
</script>
【二】新的组件间父子通信
- 子 HelloWorld.vue
<script setup>
import {ref,onUpdated} from 'vue'
defineProps({
msg: String,
})
let $emit = defineEmits(['send']) // 等同于之前的 this.$emit
const count = ref(0)
// 子传父
const name =ref('')
const handleSend=()=>{
$emit('send',name.value)
}
</script>
<template>
<p>{{ msg }}</p>
<p>{{ count }}</p>
<input type="text" v-model="name">-->{{name}}
<br>
<button @click="handleSend">点我传给父亲</button>
</template>
<style scoped>
</style>
- 父 App.vue
<template>
<h1>我是首页</h1>
{{ age }}-->
<button @click="addAge">年龄增加</button>
<HelloWorld :msg="msg" @send="handleReceive"></HelloWorld>
<p>父组件中得name:{{name}}</p>
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import {ref, reactive} from "vue";
const age = ref(10)
function addAge() {
age.value += 2
}
//父传子
const msg = ref('你好组件')
// 子传父
const name = ref('')
function handleReceive(a){
name.value=a
}
</script>
标签:vue,const,name,--,value,api,vue3,console,ref
From: https://www.cnblogs.com/zyb123/p/18362569