一、安装
-
全局安装
npm install -g @vue/cli
-
创建项目
vue create 项目名
二、目录介绍
-
src--main.js
入口文件
-
main.js介绍
//引入vue import Vue from 'vue' //引入APP组件,这是所有组件父组件 import App from './App.vue' //关闭vue生产提示 Vue.config.productionTip = false //创建vue实例对象---vm new Vue({ //.$mount('#app') 可以将这个改为 el:'#app' el:'#app', //将APP组件放入容器中 render: h => h(App), })
-
assets
存放静态资源
三、执行流程
首先写组件,
<template>
<div>
<input type="text" name="" id="" v-model="userName">
{{ userName }}
</div>
</template>
<script>
export default {
data(){
return{
userName:'张三'
}
}
}
</script>
<style>
</style>
在App.vue父组件中引入该组件,
import Dragon from './components/Dragon.vue'
接着将该组件注入到components中,
components: {
Dragon
}
并在父组件中使用该组件标签
<template>
<div id="app">
<Dragon/>
</div>
</template>
四、ref的使用
-
用于替代id类选择器
-
使用方法
<template> <div id="app"> //2. <p v-text="msg" ref="getMsg"></p> //3. <button @click="getBtn">点击</button> </div> </template> <script> export default { name: 'App', data(){ return{ //1. msg:'认真学习' } }, methods:{ //4. getBtn(){ console.log(this.$refs.getMsg); } } } </script>
this.$refs:获取被ref标注的内容
五、props的使用
使用背景
写一个共用组件,组件中的属性不唯一,比如有name、sex、age等
当不同人使用时,其显示内容不同
则在组件中使用props进行传入属性值
操作流程
<template>
<div>
{{ name }}
<hr>
{{ age }}
<hr>
{{ sex }}
<hr>
</div>
</template>
<script>
export default {
data(){
return{
}
},
//1.简单写法
// props:['name','age','sex']
//2.
props:{
name:{
//检测数据类型
type:String,
//是否必填项
required:true
},
age:{
type:Number,
//默认值
default:18
},
sex:{
type:String,
default:'男'
}
}
}
</script>
<Person name="张三" age="20" sex="男"/>
<Person name="李四"/>
六、LocalStorage使用
本地存储
-
LocalStorage.setItem(键,值)
-
其中值默认为String类型,凡不是String类型,均会调用toString
-
其中,如果时Object类型数据,则用JSON.stringify(),来转换
-
LocalStorage.getItem(键)
-
其中,如果时JSON.stringify(键)类型数据,则用JSON.parse(键),来转换
使用效果
data(){
return{
userName:'张三',
person:{
name:'zbl',
sex:'man'
}
}
},
created(){
localStorage.setItem('student',JSON.stringify(this.person))
console.log(JSON.parse(localStorage.getItem('student')));
}
SessionStorage和LocalStorage存储消除方式不一样
- SessionStorage:浏览器关闭,清除
- LocalStorage:手动/API清除
七、处理跨域
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false,
//开启代理服务器
devServer:{
proxy:{
'/dragon':{//匹配所有以/api开头请求路径
target:'http://localhost:8001',//目标服务器
pathRewrite:{'^/dragon':''},//利用正则表达添加前缀
ws:true, //支持websocket 默认true
changeOrigin:true//true 说谎,false 实话实说 默认 true
}
}
}
})
八、Vuex使用
-
安装 vuex,如果使用vue2则需要安装vuex3版本
npm i vue@3
-
创建store文件夹并创建index.js文件
-
写index.js文件
import Vuex from "vuex"; import Vue from "vue"; Vue.use(Vuex) //响应组件中的动作 const actions = {} //用于操作数据 const mutations = {} //用于存储数据 const state = {} //创建 store export default new Vuex.Store({ actions, mutations, state })
-
在main.js中引入store文件
import Vue from 'vue' import App from './App.vue' //引入store import store from './store' Vue.config.productionTip = false new Vue({ el:'#app', render: h => h(App), store })
操作案例
-
描述:实现数字加减功能
-
代码如下
组件
<template> <div> <h1>Count:{{ $store.state.sum }}</h1> <select v-model.number="n"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementOdd">当前求和为奇数再加</button> <button @click="incrementWait">等一等再加</button> </div> </template> <script> export default { name:'Count', data(){ return{ n:1 } }, methods:{ increment(){ this.$store.dispatch('add',this.n) /* 这里调用store中的action里的add方法,再根据store中的mutations的对应方法去执行 */ }, decrement(){ this.$store.dispatch('reduce',this.n) }, incrementOdd(){ this.$store.dispatch('addOdd',this.n) }, incrementWait(){ this.$store.dispatch('addWait',this.n) } }, mounted(){ console.log('Count',this); } } </script> <style> </style>
store
import Vuex from "vuex"; import Vue from "vue"; Vue.use(Vuex) //响应组件中的动作 const actions = { add(context,value){ console.log('action+调用'); context.commit('ADD',value) }, reduce(context,value){ context.commit('REDUCE',value) }, addOdd(context,value){ if(context.state.sum % 2){ context.commit('ADD',value) } }, addWait(context,value){ setTimeout(()=>{ context.commit('ADD',value) },500) } } //用于操作数据 const mutations = { ADD(state,value){ console.log('mutations的Add'); state.sum += value }, REDUCE(state,value){ state.sum -= value } } //用于存储数据 const state = { sum:0 } //创建 store export default new Vuex.Store({ actions, mutations, state })
Getters使用
背景介绍
相当于vue中的计算属性,就是对数据进行再更改,返回效果
案例
在store.js中添加如下代码
/*解释:
从state中拿到对应数据后,在getters中写一个函数用于返回值,最后直接调用bigSum即可
*/
const state = {
sum:0,
school:'尚硅谷',
subject:'前端Vue'
}
const getters = {
bigSum(state){
return state.sum * 10
}
}
mapState和mapGetters
背景
为了将代码简单化,我们不再像如下这种写法
<h1>Count:{{$store.state.sum }}</h1>
<h3>放大10倍后:{{$store.getters.bigSum}}</h3>
<p>我在B站学习{{ $store.state.school }}的{{ $store.state.subject }}</p>
而利用mapState将重复的内容去掉,写法如下:
<!--利用计算属性去将state和getters中的内容进行赋值新的变量,再直接将该变量放到{{}}即可-->
<template>
<div>
<h1>Count:{{sum }}</h1>
<h3>放大10倍后:{{bigSum}}</h3>
<p>我在B站学习{{ school }}的{{ subject }}</p>
</div>
</template>
<script>
computed:{
//借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({sum:'sum',school:'school',subject:'subject'})
//数组写法
...mapState(['sum','school','subject']),
...mapGetters(['bigSum'])
}
</script>
...这里的三个点,即将其内容依次取出显示
mapMutations/mapActions
背景
简化代码
写法
传统写法如下:
methods:{
increment(){
this.$store.dispatch('add',this.n)
},
decrement(){
this.$store.dispatch('reduce',this.n)
}
更改之后的写法:
引入mapMutations/mapActions
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
//对象写法,数组写法即:名字和名字相同
...mapActions({incrementOdd:'addOdd',incrementWait:'addWait'})
九、数据存入state
案例
<template>
<div>
姓名:<input type="text" v-model="name"/>
<button @click="add">添加</button>
<hr>
<ul>
<li v-for="s in studentList" :key="s.id">{{ s.name }}</li>
</ul>
</div>
</template>
<script>
import {nanoid} from "nanoid";
export default {
name:'Student',
data(){
return{
name:''
}
},
methods:{
add(){
console.log("执行add");
const studentObj = {id:nanoid(),name:this.name}
console.log("执行前");
this.$store.commit('ADD_STUDENT', studentObj)
this.name = ''
console.log(studentObj);
}
},
computed:{
studentList(){
return this.$store.state.studentList
}
}
}
</script>
<style>
</style>
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex)
//响应组件中的动作
const actions = {
}
//用于操作数据
const mutations = {
ADD_STUDENT(state,value){
state.studentList.unshift(value)
}
}
//用于存储数据
const state = {
studentList:[
{id:'001',name:'张三'}
]
}
//创建 store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
十、模块化开发+name
背景
-
在之前的写法中我们可以得知,每个store文件中只有一个如下的内容
actions:{}, mutations:{}, state:{}, getters:{}
-
而如果有多个组件分别分给不同的人开发,那么他们都会写入这一个中,就会出现开发困难,可读性差,git冲突。于是乎,我们可以创建多个以上内容。
const countOptions = { namespace:true, actions:{}, mutations:{}, state:{}, getters:{} }, const studentOptions = { namespace:true, actions:{}, mutations:{}, state:{}, getters:{} } //那么这里,就写了两个对应模块开发
案例
<template>
<div>
姓名:<input type="text" v-model="name"/>
<button @click="add">添加</button>
<hr>
<ul>
<li v-for="s in studentList" :key="s.id">{{ s.name }}</li>
</ul>
</div>
</template>
<script>
import {nanoid} from "nanoid";
export default {
name:'Student',
data(){
return{
name:''
}
},
methods:{
add(){
console.log("执行add");
const studentObj = {id:nanoid(),name:this.name}
console.log("执行前");
this.$store.commit('studentOptions/ADD_STUDENT', studentObj)
this.name = ''
console.log(studentObj);
}
},
computed:{
studentList(){
return this.$store.state.studentOptions.studentList
}
}
}
</script>
<style>
</style>
<template>
<div>
<h1>Count:{{sum }}</h1>
<h3>放大10倍后:{{bigSum}}</h3>
<p>我在B站学习{{ school }}的{{ subject }}</p>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
export default {
name:'Count',
data(){
return{
n:1
}
},
methods:{
// increment(){
// this.$store.dispatch('add',this.n)
// },
// decrement(){
// this.$store.dispatch('reduce',this.n)
// },
...mapMutations('countOptions',{increment:'ADD',decrement:'REDUCE'}),
// incrementOdd(){
// this.$store.dispatch('addOdd',this.n)
// },
// incrementWait(){
// this.$store.dispatch('addWait',this.n)
// },
//对象写法,数组写法即:名字和名字相同
...mapActions('countOptions',{incrementOdd:'addOdd',incrementWait:'addWait'})
},
computed:{
//借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({sum:'sum',school:'school',subject:'subject'})
//数组写法
...mapState('countOptions',['sum','school','subject']),
...mapGetters('countOptions',['bigSum'])
},
mounted(){
console.log('Count',this);
}
}
</script>
<style>
</style>
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex)
const countOptions = {
namespaced:true,
actions:{
// add(context,value){
// console.log('action+调用');
// context.commit('ADD',value)
// },
// reduce(context,value){
// context.commit('REDUCE',value)
// },
addOdd(context,value){
if(context.state.sum % 2){
context.commit('ADD',value)
}
},
addWait(context,value){
setTimeout(()=>{
context.commit('ADD',value)
},500)
}
},
mutations:{
ADD(state,value){
console.log('mutations的Add');
state.sum += value
},
REDUCE(state,value){
state.sum -= value
}
},
state:{
sum:0,
school:'尚硅谷',
subject:'前端Vue'
},
getters:{
bigSum(state){
return state.sum * 10
}
}
}
const studentOptions = {
namespaced:true,
actions:{},
mutations:{
ADD_STUDENT(state,value){
state.studentList.unshift(value)
}
},
state:{
studentList:[
{id:'001',name:'张三'}
]
},
getters:{}
}
//创建 store
export default new Vuex.Store({
modules:{
countOptions,
studentOptions
}
})
十一、路由基本使用
路由安装
-
在现在的vue-router,默认支持的是vue3,所以我们需要指定router的版本,若用vue2则需要用router3的版本
npm i vue-router@3
-
安装成功之后
在main.js引入并使用
import VueRouter from 'vue-router' Vue.use(VueRouter)
-
创建router文件夹,写入如下内容
import VueRouter from "vue-router"; //引入两个组件 //这两个组件分别需要在里面的script中写入对应name import Home from "../views/Home.vue"; import About from "../views/About.vue"; //暴露VueRouter实例 export default new VueRouter({ //配置路由 routes:[ { path:'/about',//浏览器路径 component:About//组件名称 }, { path:'/home', component:Home } ] })
-
将写好的router文件夹,引入到main.js中
import router from "./router"; //在new Vue中引入router
-
在App.vue写入
<router-link to="/about">About</router-link>
,用于路由跳转 -
写入
<router-view></router-view>
,用于显示切换内容
十二、嵌套路由
背景
- 点击路由导航出现第二个路由导航再接着点第二个显示内容
操作流程
-
写一个新的组件
将该组件注册到router.js中,如下:
import VueRouter from "vue-router"; import Home from "../views/Home.vue"; import About from "../views/About.vue"; import Message from "../views/about/Message.vue"; import Test01 from "../views/about/Test01.vue"; export default new VueRouter({ routes:[ { path:'/about', component:About, children:[ { path:'message', component:Message }, { path:'test01', component:Test01 } ] }, { path:'/home', component:Home } ] })
-
新组件需要写
和 这里的访问路径必须是/父路由/子路径
十三、路由_query参数
背景
- 利用一个组件显示多个信息,比如淘宝中的商品信息点进去,每个页面布局一样
操作流程
-
创建一个共用组件
<template> <div> 用户ID:{{ $route.query.id }} 用户姓名:{{ $route.query.title }} </div> </template> <script> export default { name:'Details' } </script> <style> </style>
-
在路由导航组件中写入如下内容
<template> <div> message <ul> <li v-for="m in messageList" :key="m.id"> <router-link :to="{ path:'/about/message/details', //访问路径 query:{ //传入参数 id:m.id, title:m.title } }"> {{ m.title }}</router-link> </li> </ul> <hr> <router-view></router-view> </div> </template> <script> export default { name:'Message', data(){ return{ //这里模仿axios请求到的数据 messageList:[ {id:'001',title:'消息001'}, {id:'002',title:'消息002'}, {id:'003',title:'消息003'}, {id:'004',title:'消息004'} ] } } } </script> <style> </style>
十四、路由命名
背景
- 给路由起个名字
- 简化路径跳转复杂性
操作流程
-
传统写法
<ul> <li v-for="m in messageList" :key="m.id"> <router-link :to="{ path:'/about/message/details', query:{ id:m.id, title:m.title } }"> {{ m.title }}</router-link> </li> </ul>
-
更改之后写法
首先需要给路由起个名字
routes:[ { path:'/about', component:About, children:[ { path:'message', component:Message, children:[ { name:'detailsName', //这里 path:'details', component:Details } ] }, { path:'test01', component:Test01 } ] }, { path:'/home', component:Home } ] })
<ul> <li v-for="m in messageList" :key="m.id"> <router-link :to="{ // path:'/about/message/details', name:'detailsName', //将path换成name即可 query:{ id:m.id, title:m.title } }"> {{ m.title }}</router-link> </li> </ul>
十五、路由_params参数
背景
-
相当于发送请求是
http:localhost:8080/test/张三/23
并没有使用
http:localhost:8080/test?name=张三&age=23
操作流程
-
创建共用组件
<template> <div> 用户ID:{{ $route.params.id }} <!--注意这里使用params--> 用户姓名:{{ $route.params.title }} </div> </template> <script> export default { name:'Details' } </script> <style> </style>
-
在路由导航中写入如下内容
<ul> <li v-for="m in messageList" :key="m.id"> <router-link :to="{ // path:'/about/message/details', name:'detailsName', params:{ id:m.id, title:m.title } }"> {{ m.title }}</router-link> </li> </ul>
注意:params使用,不能使用path指定路径,必须用name,如若不用则会报错
十六、路由_props使用
背景
-
为了简化繁琐的获取数据,比如:
用户ID:{{ $route.params.id }} <!--注意这里使用params--> 用户姓名:{{ $route.params.title }}
-
则利用props参数来进行更改简化
第一步:设置路由中的内容
routes:[ { path:'/about', component:About, children:[ { path:'message', component:Message, children:[ { name:'detailsName', path:'details/:id/:title', component:Details, props($route){ //这里<------------- return{ id:$route.params.id, title:$route.params.title } } } ] } ]
第二步设置组件中的props内容
export default { name:'Details', props:['id','title'] }
十七、路由_replace属性
背景
- 在页面浏览时,会产生浏览记录,而在普通的router-link中会进行push,也就是压栈,而replace即将当前浏览记录替换。
操作流程
-
在router-link中添加如下内容即可
<router-link replace to="/path">跳转replace</router-link>