网站程序开发外包,广西专业建网站,整站优化哪家专业,计算机专业学什么vue3
官网#xff1a;简介 | Vue.js (vuejs.org)
1. 环境搭建与启动 npm create vuelatest
这一指令将会安装并执行 create-vue#xff0c;它是 Vue 官方的项目脚手架工具
之后#xff0c;你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示#xff1a;
✔ …vue3
官网简介 | Vue.js (vuejs.org)
1. 环境搭建与启动 npm create vuelatest
这一指令将会安装并执行 create-vue它是 Vue 官方的项目脚手架工具
之后你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示
✔ Project name: … your-project-name
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / YesScaffolding project in ./your-project-name...
Done.注意project name 输入的时候不要有大写字母
然后会提示
Done. Now run:cd first_vue (刚刚填写的project名称)npm installnpm run dev按照要求 进入 first_vue执行 npm install npm run dev VITE v4.4.9 ready in 494 ms➜ Local: http://localhost:5173/➜ Network: use --host to expose➜ press h to show help出现以上界面就成功了在浏览器界面访问 http://localhost:5173/ 可以看到 vue 界面
使用 vscode 进入项目会发现有很多的文件夹 创建好项目了也可以直接在vscode的左下角使用 npm 脚本 下载 volar 插件 2. 修改端口
vue3 默认端口5173
想要把端口号修改为9090在vite.config.js中写入
server: {port: 9090,//端口号host: true,//ip地址 或 0.0.0.0 或 loaclhostopen: false, //启动后是否自动打开浏览器https: false, // 是否开启 https
},3. 组合式API
3.1 setup 执行时间比beforeCreate还要早 setup函数中获取不到 this setup函数中的 数据 和 函数需要 return简化请看第4点 如果在 script中 使用setup就不需要return了语法糖帮你return了。 !-- script加上setup允许在script中直接编写组合式 api--script setupconst messge qwq;const hello hello vue3const show () {console.log(messge);}/scripttemplatep {{ hello }}/pbutton clickshowbutton/button/template3.2 reactive 和 ref 函数 例如
!-- script加上setup允许在script中直接编写组合式 api--
script setupimport { reactive } from vue
// 接受对象参数传递并返回一个响应式的对象响应式理解的来说就是同步变化
const state reactive({count:100
})
// 这里{count:100} 是新建了一个匿名对象作为 reactive 的参数js中的对象就是 name:value 键值对
const setCount () {state.count;
}/scripttemplatedivdiv {{ state.count }} /divbutton clicksetCount 1 /button/div
/template
这里不一样的是 既可以接收简单类型又可以接收对象类型
本质在原有传入数据的基础上外层包了一层对象实际上还是借助了 reactive
注意在 script 中访问 ref 定义的数据的时候需要通过.value但是在template中 不需要
例如
!-- script加上setup允许在script中直接编写组合式 api--
script setupimport { ref } from vue
const count ref(0)
console.log(count.value); /scripttemplatediv{{ count }} /divdivbutton click() { count } 1 /button/div
/template 3.3 computed 例如
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import { computed, ref } from vue;const list ref([1,1,4,5,1,4])
const computedList computed(() {return list.value.filter(i i 2)}
)
const userInput ref()const addValue (userInput) {if (userInput ! ) {list.value.push(parseInt(userInput))}
}/scripttemplatedivdivlist{{ list }}/divdiv过滤之后的list{{ computedList }}/divdivinput v-modeluserInput placeholder输入一个值 /button clickaddValue(userInput)添加值到list/button/div/div/template
注意computed中也可以编写 get set方法可以用来将 ref 对象变为可写 ( ref 对象默认可读)
例如
script setup
import { computed, ref } from vue;
const tmp ref(3)
const tmpComputed computed({get:() {return tmp.value 1},set:(val) {tmp.value val}
})tmpComputed.value 2
console.log(tmp.value)
console.log(tmpComputed.value)/script3.4 watch
作用侦听一个或者多个数据的变化数据变化时立即执行回调函数
使用
导入 watch 函数执行 watch 函数传入要侦听的响应式数据ref 对象和 回调函数
例如
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import { watch, computed, ref } from vue;const number ref(0)
const name ref(张三)const changNumber () {number.value;
}const changeName () {name.value 李四
}// 监视单个 ref对象 number
// 注意这里是对象不需要取值
// 语法为watch( ref对象, (newValue, oldValue) {})
watch(number, (newValue, oldValue) {console.log(newValue, oldValue);
})// 监视多个 ref 对象number 和 name
// 语法为watch([ref对象1,ref对象2...], (newArr, oldArr) {})
watch([number, name], (newArr, oldArr) {console.log(newArr, oldArr);
})/scripttemplatedivdiv{{ number }}button clickchangNumberchange number/button/divdiv{{ name }}button clickchangeNamechange name/button/div/div/template这里其实 oldValue 和 oldArr可以忽略具体情况具体分析如果不需要旧值不接收就好了这也是newValue等是第一个参数的原因
immediate 和 deep
immediate:
添加immediate对象可以让监视在程序加载时立即启动一次而不需要等待第一次值改变。
例如
watch(number, (newValue, oldValue) {console.log(newValue, oldValue);
},{immediate:true
})deep:
deep 是深度监视watch的默认监视进行的是浅层监视对于简单类型的值可以直接监视但监视不到复杂类型内部数据的变化。
例如
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import { watch, computed, ref } from vue;
const person ref({name:张三,age:18,sex:1
})const changeAge () {person.value.age;
}watch(person, (newValue) {console.log(newValue);
},{deep:true
})/scripttemplatedivdiv{{ person }}/div button clickchangeAgeage/button/div/template使用deep相当于监视了对象的所有属性如果我只需要监听一个特定的属性呢
也可以实现例如
watch(()person.value.age, (newValue){console.log(newValue);
})就是把第一个参数从对象换成了一个返回你需要监听属性的函数 3.5 生命周期
每一个生命周期都有一个对应的方法进行到该生命周期就会触发这个方法。 例如
onMounted(() {console.log(mounted生命周期函数)
})3.6 父子通信
3.6.1 在父组件中引入子组件
局部导入
在components包下写子组件例如sonCom.vue
然后在父组件中 import 导入后直接在template中使用标签使用
例如
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import sonCom from ./components/sonCom.vue
/script
templatedivh3 父组件 /h3/divdivsonCom/sonCom/div
/template
style
/style3.6.2 父传子 例如父组件
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import sonCom from ./components/sonCom.vue
import { ref } from vue;const money ref(10000)/scripttemplatedivh3 父组件 /h3/divdivsonCom car兰博基尼 :moneymoney/sonCom/div/templatestyle/style子组件sonCom
script setup
const props defineProps({car: String,money: Number
})
console.log(props.car); //这里注意脚本中需要写 props.属性但是模板中不需要写直接用属性/scripttemplatediv classsonp我是子组件/pp我是父组件中继承了{{ car }}, {{ money }}/p/div/templatestyle
.son{border: solid 2px brown;padding: 30px;
}
/style3.6.3 子传父 如果要修改父组件的值
调用我需要做的修改父组件的值的方法在方法中调用 emit 函数语法为 emit(事件名, 参数)使用defineEmits方法提供 emit 函数语法const emit defineEmits([事件1, 事件2])理解成注册事件就行父组件在 子组件标签中 用emit传来的事件名xxxx绑定子组件的事件定义xxxx其中可以使用emit传来的参数
例如父组件
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import sonCom from ./components/sonCom.vue
import { ref } from vueconst money ref(10000);
const earnMoney () {money.value 50;
}
const useMoney (restMoney) {money.value restMoney
}/scripttemplatedivh3 父组件 /h3p当前money{{ money }}button clickearnMoney 赚钱 /button/p/divdivsonCom car兰博基尼 :moneymoney useMoneyuseMoney/sonCom/div/templatestyle/style子组件
script setup
const props defineProps({car: String,money: Number
})
const emit defineEmits([useMoney])
const useMoney () {emit(useMoney, 5)
}/scripttemplatediv classsonh3我是子组件/h3p我是父组件中继承了{{ car }}, {{ money }}button clickuseMoney 花钱 /button/p/div/templatestyle
.son{border: solid 2px brown;padding: 30px;margin-top: 10px;
}
/style3.7 模板引用 与 defineExpose 这样也可以实现子传父。 3.8 provide 和 inject 跨层传递 3.8 defineOptions 3.9 defineModel
想要使用首先要在vite中修改
plugins: [vue({script: {defineModel: true, // 启用defineModel}}),],4. pinia
简介 | Pinia (vuejs.org)
Pinia 是 Vue 的专属状态管理库它允许你跨组件或页面共享状态。
安装
npm install pinia
导包
import { createApp } from vue
import { createPinia } from pinia
import App from ./App.vueconst pinia createPinia()
const app createApp(App)app.use(pinia)
app.mount(#app)4.1 快速入门
使用
在 src 下新建文件夹 store 用来存储仓库在 store 下新建仓库 ( js ) 并使用defineStore函数创建对象在需要使用仓库的地方 实例化仓库对象直接调用对象中的值 和 函数
例如
testStore
import { defineStore } from pinia
import { ref } from vue;
export const useTestStore defineStore(testStore, () {const count ref(0);const subCount () {count.value--;}const addCount () {count.value;}return{count,subCount,addCount,}
})App.vue:
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import sonCom from ./components/sonCom.vue;
import sonCom2 from ./components/sonCom2.vue;
import { useTestStore } from ./store/test;const testStore useTestStore() //创建实例/scripttemplatedivh1我是父组件 -- {{ testStore.count }}/h1sonCom/sonComsonCom2/sonCom2/div
/templatestyle/stylesonCom.vue:
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import { useTestStore } from ../store/test;
const testStore useTestStore()/scripttemplatedivh2我是儿子组件 -- {{ testStore.count }}button clicktestStore.addCount /button/h2/div
/templatestyle/style4.2 异步请求
我们使用axios来发送异步请求例如
import { defineStore } from pinia;
import axios from axios
import { ref } from vue;export const useaxiosStore defineStore(axiosStore, () {const channellist ref([])const getList async() { //async 表示异步函数 const { data: { data } } await axios.get(http://localhost:8080/pinia) // 等待数据获取完毕channellist.value data.channels}return{channellist,getList}
})app.vue
!-- script加上setup允许在script中直接编写组合式 api--
script setup
import { useaxiosStore } from ./store/axios;
const axiosStore useaxiosStore() //创建实例
/script
templatedivbutton clickaxiosStore.getList 获取数据 /buttonulli v-fori in axiosStore.channellist :keyi.id {{ i.name }} /li/ul/div
/template
style
/stylejava接收请求并返回数据
package com.zhx.controller;import com.zhx.pojo.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import java.io.PipedReader;
import java.util.*;RestController
public class piniaController {GetMapping(/pinia)public Result send(){class data{private ListObject channels;private String message;public data(ListObject channels, String message) {this.channels channels;this.message message;}public ListObject getChannels() {return channels;}public void setChannels(ListObject channels) {this.channels channels;}public String getMessage() {return message;}public void setMessage(String message) {this.message message;}}ListObject list new ArrayList();for(int i1;i5;i){MapString, Object map new HashMap();map.put(id, i);map.put(name, name:i);list.add(map);}return Result.success(new data(list, qwq));}
}这里还需要解决一下跨域请求使用 java 的 config类
package com.zhx.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;Configuration
public class CorsConfig {Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource();CorsConfiguration config new CorsConfiguration();// 允许哪些源访问config.addAllowedOrigin(http://localhost:5173);// 允许哪些 HTTP 方法config.addAllowedMethod(GET);source.registerCorsConfiguration(/pinia/**, config);return new CorsFilter(source);}
} 4.3 仓库解构storeToRefs(store)
我们之前都是直接导入仓库然后实例化然后使用 .进行访问如果想要直接进行解构的话需要注意两点
解构 store 的状态需要使用storeToRefs(store)解构 store 的 action组合式中就是函数 直接解构
因为解构会破坏响应性但是 action 比如说函数没有响应性可言就是用就完事了。
例如
script setup
import { storeToRefs } from pinia
const store useCounterStore()
// 需要调用方法
const { name, doubleCount } storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } store
/script4.4 pinia持久化
快速开始 | pinia-plugin-persistedstate (prazdevs.github.io)
我们的响应式数据变更之后如果刷新页面响应式数据会重置如果我们需要对响应式数据进行一个持久化那么就可以使用上面的插件。
安装npm i pinia-plugin-persistedstate
配置
import { createPinia } from pinia
import piniaPluginPersistedstate from pinia-plugin-persistedstateconst pinia createPinia()
pinia.use(piniaPluginPersistedstate)用法
创建 Store 时将 persist 选项设置为 true。
import { defineStore } from piniaexport const useStore defineStore(main,() {const someState ref(你好 pinia)return { someState }},{persist: true, //实际上就是加了一个参数第三个参数把persist改成true},
)还有一些配置操作可以参考官网 配置 | pinia-plugin-persistedstate (prazdevs.github.io)
例如我不希望把整个 state 进行持久化我们可以使用 path 进行注册
import { defineStore } from pinia
import { ref } from vue;
export const useTestStore defineStore(testStore, () {const count ref(0);const name ref(feixin)const subCount () {count.value--;}const addCount () {count.value;}return{count,subCount,addCount,name,}
},{persist: {paths:[count] // 这里就只对 count 进行了持久化而name没有}
})5. 常用指令
指令作用v-bind为HTML标签绑定属性值如设置hrefcss样式等 v-bind:href 可以省略为 :hrefv-model在表单元素上创建双向数据绑定v-on为HTML标签绑定事件v-if类下v-else-if条件性的渲染某元素判定为true时渲染否则不渲染v-else类上v-show根据条件展示某元素区别在于切换的是display属性的值v-for列表渲染遍历容器的元素或者对象的属性 v-bind 和 v-model
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlevue test/titlescript src../js/vue.js/script
/head
bodydiv idappa v-bind:hrefurl这是一个链接/a!-- v-bind:href 可以省略为 :href --input typetext v-modelurl/div
/body
scriptnew Vue({el: #app,data:{url:https://www.baidu.com}})
/script
/html可以实现更改表单中的网址旁边的a标签绑定的网址也会发生相应的变化 注意通过 v-bind 或者 v-model 绑定的变量必须在数据模型中声明。 v-on
可以绑定很多时间比如clickblurfocus 与 js 事件类似
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlevue test/titlescript src../js/vue.js/script
/headbodydiv idappinput typebutton valueclick me v-on:clickhandle()!-- v-on:click可以简化为click --/div
/body
scriptnew Vue({el: #app,data: {url: https://www.baidu.com},methods: {handle: function () {alert(i have been clicked);}},})
/script/html效果就是点击后触发事件 条件指令 v-if v-else-if v-else v-show:
ifelse-ifelse 是一起配套使用的
例如
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlevue test/titlescript src../js/vue.js/script
/headbodydiv idapp年龄input typetext v-modelage经判定为span v-ifage35年轻人 35岁以下/spanspan v-else-ifage35 age60中年人 35-60/spanspan v-else老年人 60以上/span!-- 注意这里else后面没东西了 --/div
/body
scriptnew Vue({el: #app,data: {age:20,},})
/script/html效果为修改输入框中的值后面的判定字会改变if 这一套 如果 条件为 else 的话标签直接不会在浏览器中被渲染也就是根本不会出现在浏览器源码当中。
v-show:
上述效果同样可以通过v-show来实现。
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlevue test/titlescript src../js/vue.js/script
/headbodydiv idapp年龄input typetext v-modelage经判定为span v-ifage35年轻人 35岁以下/spanspan v-else-ifage35 age60中年人 35-60/spanspan v-else老年人 60以上/spanbrbr年龄input typetext v-modelage经判定为span v-showage35年轻人 35岁以下/spanspan v-showage35 age60中年人 35-60/spanspan v-showage60老年人 60以上/span/div
/body
scriptnew Vue({el: #app,data: {age:20,},})
/script/html效果是一样的区别在于v-show 如果条件为 false 的话标签依然会被浏览器渲染不过是被display:none设置了不展示 v-for: 遍历数据对象
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlevue test/titlescript src../js/vue.js/script
/headbodydiv idappdiv v-foraddr in addrs :keyindex{{addr}}/divhrdiv v-for(addr, index) in addrs :keyindex{{index 1}} : {{addr}}/div/div
/body
scriptnew Vue({el: #app,data: {addrs:[beijing,shanghai,xian,guilin]},})
/script/html6. Element -plus
6.1 安装
安装 | Element Plus (element-plus.org)
根据文档在当前目录下安装 或者使用以下方式
vue3vite2增加element-plus的CDN链接打包构建 - 掘金 (juejin.cn)
按需引入 pnpm element-plus pnpm add -D unplugin-vue-components unplugin-auto-import 在vite.config.js中配置 import AutoImport from unplugin-auto-import/vite //---1
import Components from unplugin-vue-components/vite //---2
import { ElementPlusResolver } from unplugin-vue-components/resolvers//---3export default defineConfig({plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()] //---1}),Components({resolvers: [ElementPlusResolver()] //---2})],resolve: {alias: {: fileURLToPath(new URL(./src, import.meta.url))}}
})6.2 使用
创建如下目录 在ElementView.vue中编写
script
export default{}
/scripttemplatedivel-row classmb-4el-buttonDefault/el-buttonel-button typeprimaryPrimary/el-buttonel-button typesuccessSuccess/el-buttonel-button typeinfoInfo/el-buttonel-button typewarningWarning/el-buttonel-button typedangerDanger/el-button/el-row!-- 各种你想添加的组件 -- /div
/template
style/style在 App.vue中编写
script
import ElementView from ./views/element/elementView.vue;export default{components: { ElementView }
}/scripttemplatedivElementView/ElementView/div
/templatestyle/style
即可导入。 6.3 常见组件
组件 | Element
进去复制粘贴使用懂 6.4 引入
引入组件之后需要在components中声明一下才可以使用
例如
script
import { Menu as IconMenu, Message, Setting } from element-plus/icons-vue;
// 这里引入了组件
export default {data() {return {searchForm: {name: ,gender: ,entryDate: [],}}},components: {Message, Setting//这里需要声明},methods: {query() {alert(JSON.stringify(this.searchForm));},sizeChange(val){alert(每页记录数变化 val)},currentChange(val){alert(页码发生变化 val)},}
}
/script7. pnpm
npm install -g pnpm 8. ESlint 配合 Prettier
参考旁边的文件 大事件管理系统中的 ESlint配置 9. husky 别打上去
pnpm dlx husky-init pnpm install 暂存区 eslint 校验 10. axios 配置 10.1. 创建 axios 实例
们会使用 axios 来请求后端接口, 一般都会对 axios 进行一些配置 (比如: 配置基础地址等)
一般项目开发中, 都会对 axios 进行基本的二次封装, 单独封装到一个模块中, 便于使用
安装 axios
pnpm add axios新建 utils/request.js 封装 axios 模块 利用 axios.create 创建一个自定义的 axios 来使用 http://www.axios-js.com/zh-cn/docs/#axios-create-config
import axios from axiosconst baseURL http://big-event-vue-api-t.itheima.netconst instance axios.create({// TODO 1. 基础地址超时时间
})instance.interceptors.request.use((config) {// TODO 2. 携带tokenreturn config},(err) Promise.reject(err)
)instance.interceptors.response.use((res) {// TODO 3. 处理业务失败// TODO 4. 摘取核心响应数据return res},(err) {// TODO 5. 处理401错误return Promise.reject(err)}
)export default instance10.2. 完成 axios 基本配置
import { useUserStore } from /stores/user
import axios from axios
import router from /router
import { ElMessage } from element-plusconst baseURL http://big-event-vue-api-t.itheima.netconst instance axios.create({baseURL,timeout: 100000
})instance.interceptors.request.use((config) {const userStore useUserStore()if (userStore.token) {config.headers.Authorization userStore.token}return config},(err) Promise.reject(err)
)instance.interceptors.response.use((res) {if (res.data.code 0) {return res}ElMessage({ message: res.data.message || 服务异常, type: error })return Promise.reject(res.data)},(err) {ElMessage({ message: err.response.data.message || 服务异常, type: error })console.log(err)if (err.response?.status 401) {router.push(/login)}return Promise.reject(err)}
)export default instance
export { baseURL }
11. 打包
npm run build 可以进行打包打包之后会出现在dist中