是自己的一些总结
nvm–node版本管理
nvm ls //列出已安装版本
nvm current //当前版本
nvm list available //可选择安装的版本
nvm install //安装node
nvm use 14.20.1 //切换为14版本。16.14.2
nvm uninstall :卸载指定node
webpack–用于搭框架
webpack 4.x和5.x的版本默认约定:
打包入口文件src-> index.js
输出文件路径dist-> main.js
mode–指定webpack构建模式
mode:‘development’//用于开发,速度快,不压缩代码
mode:‘production’//用于发布阶段,速度慢,压缩代码
webpack-dev-server–监听项目源代码变化,自动打包构建
Babel–转换代码,以兼容旧版本
loader加载器–协助webpack打包特定的文件模块
webpack默认只能打包.js
test表示文件类型,use调用对应loader
module: {
rules: [
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
}
devtool:‘eval-source-map’–生成的 Source Map保证"运行时报错的行数"与"源代码的行数"保持一致。适合开发环境
nosources-source-map–只定位报错的具体行数,不暴露源码。适合生产环境
Vue的实例对象
const vm = new Vue({
// el是固定写法,表示当前vm要控制页面上的区域,接收值是选择器
el: '#app',
// data 是要渲染到页面上的数据
data: {
count: 0
},
// methods 是定义事件的处理函数
methods: {
})
指令–模版语法,用于渲染页面
内容渲染指令
v-text 覆盖元素内默认值
{{}} 插值表达式
v-html //有安全问题,易导致XSS攻击
属性绑定指令–v-bind
v-bind: 指令可以简写为 :
data:{
inputValue:'内容'
}
<input type="text" v-bind:placeholder="inputValue"/>
事件绑定指令–v-on
v-on: 指令可以被简写为 @
v-on:click、v-on:keyup
@click.once//一次点击生效
xx.unshift(a) //在数组前面添加a
$event–原生 DOM 的事件对象 e
事件修饰符–对事件触发进行控制
.prevent阻止默认行为
.stop阻止事件冒泡
v-model修饰符
v-model.number–将输入值改为数值
v-model.trim–过滤首尾空白字符
过滤器–用于文本格式化,vue2专属
filters: {} 过滤器
Vue.filter(name,callback) 全局过滤器
{{ xxx | 过滤器名}}
:xx = "xxx | 过滤器名"
val.slice(1)//从索引1往后截取
this.list.filter(item=>item.id!==id)//列表过滤,保留id不同的项
'abc'.indexOf('b')//结果为1
watch侦听器–监视数据变化
watch: {} 侦听器
data: {
id:'',
info: {
user: 'admin',
}
}
id(new,old) //数据名作为方法名,新值在前,旧值在后
'info.user'(new,old) //子属性要加单引号
computed计算属性–
computed: {}
async–用于声明异步函数,返回Promise对象。可以使用await等待操作完成。
解构赋值
const { data: res }=函数//将解构出的data数据,重命名为res。
props–让组件接收数据,只读,不可修改,可以设默认值
发送:
<Demo name="xxx"/>
接收:
1.props:['name',] //指向一个数组
2.props: {
name: {
default: 0, //默认为0
type: Number,// 类型 Number
required: true// 必填项
}
}
scoped 解决组件的样式冲突问题–自动给组件内所有标签 添加相同的自定义属性
<style lang="less" scoped>
/deep/–原理是给样式加一个唯一的自定义属性,使其生效
/deep/ h5 相当于:
[data-v-xxx] h5
生命周期函数–三个阶段
创建–>
beforeCreate–在内存创建组件之前
created–创建组件后
beforeMount–渲染组件之前
mounted–渲染组件后(重要)
运行–>
beforeUpdate–运行组件之前
updated–
销毁–>
beforeDestroy–销毁组件之前(重要)
destroyed–
父子之间传值
父:<xxx :msg="message" @numchange="getNew""></xxx>
子:props: ['msg'] //接受父的值
this.$emit('numchange') //调用父的自定义事件
this.$off('numchange') //解绑事件
this.$emit('numchange','666')//向父传值
兄弟之间传值
先创建eventBus模块,共享Vue实例,export default new Vue()
import bus from './eventBus.js'
兄弟A:bus.$emit('share','666') //传值出去
兄弟B:bus.$on('share', val => {console.log(val)}) //接收并定义函数
ref–给元素或者子组件打标签
<h1 ref="xx"></h1>
this.$refs.xx.style.color='red'
this.$nextTick(callback)–DOM更新后再执行回调函数
key–虚拟DOM的标识。以index作为key,进行逆序操作会出现问题
查询数据–利用计 算属性和列表过滤,显示包含关键字的信息
computed:{
函数(){
return this.列表.filter((p)=>{
return p.对象.indexOf(关键字) !== -1
})
}
}
sort–js的排序方法
arr.sort((a,b)=>{
return a-b //升序,b-a为逆序
})
set–插入数据
Vue.set(目标,键,值) //不能给vm的根数据对象添加属性
vm.$set()
xx:{y:['a','b','c'],}
this.$set(this.xx.y,0,'aa')//修改第一个值
vue包装修改数组的方法,实现对数组的监测–push、pop、shift、splice、
xx.splice(0,1,{键:值}) //更改数组索引为0的数据,不能用xx[0],应该用splice
v-cloak–与css配合,可解决网速慢时页面展示出{{xxx}}的问题
<style>
[v-cloak]{
display:none;
}
</style>
<h2 v-cloak>{{name}}</h2>
v-once–所在节点在初次渲染后,视为静态
<h2 v-once>初始化的值是:{{n}}</h2>
v-pre–跳过编译过程
<h2 v-pre>我是11,有什么插值表达式的话不要用</h2>
自定义指令–不要用驼峰命名
(1).bind:指令与元素成功绑定时调用。
(2).inserted:指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。
局部定义:
new Vue({ new Vue({
directives:{指令名:配置对象} 或 directives:{指令名:回调函数}
}) })
data:{
n:1,}
<span v-big="n"></span>
big(element,binding){
console.log('big',this) //此处的this是window
element.innerText = binding.value * 10
},
组件–实现特定功能的代码集合
const hello= Vue.extend(options) 可简写为:const hello= options
//非单文件组件
//创建hello组件
const hello = Vue.extend({
template:`
<div>
<h2>你好</h2>
</div>
`,
data(){
}
})
//注册组件(局部注册)
components:{
hello,
}
//全局注册组件
Vue.component('hello',hello)
VueComponent–组件本质是名为VueComponent的构造函数
每次调用Vue.extend,返回全新的VueComponent。
组件的this是【VueComponent实例对象】。
vm和vc有相同的属性和方法,不同的是vm能通过el决定为哪个容器服务。
render–是一个函数,将App组件放入容器中
//render: 参数 => 返回值
render: h => h(App)
相当于==>
render(h){
return h(App)
}
vue.config.js–定制脚手架
mixin–提取多个组件共用的配置,成一个混入对象
定义:
export const A ={
data(){....},
methods:{....}
....
}
使用:
import {A} from '....'
全局混入:Vue.mixin(A)
局部混入:mixins:['A']
plugin–插件,定义全局使用的方法、指令等,增强vue
定义:
export default {
install(Vue, options) {
Vue.filter(....)
Vue.directive(....)
Vue.mixin(....)
Vue.prototype.$myMethod = function () {...}
}
}
使用:
Vue.use()
浏览器本地存储
SessionStorage内容,关闭浏览器窗口消失。
LocalStorage内容,手动清除才会消失。
全局事件总线–任意组件间通信
new Vue({
el:'#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线
},
})
提供数据:
this.$bus.$emit('xxx',数据)
接收数据:
mounted() {
this.$bus.$on('xxx',(data)=>{
})
},
销毁:
beforeDestroy() {
this.$bus.$off('xxx')
},
消息订阅与发布(pubsub)–任意组件间通信
安装pubsub: npm i pubsub-js
引入: import pubsub from 'pubsub-js'
提供数据:
pubsub.publish('xxx',数据)
接收数据:
mounted() {
this.pid=pubsub.subscribe('xxx',(data)=>{
})
},
销毁:
beforeDestroy() {
pubsub.unsubscribe('xxx')
},
vue封装的动画和过渡
动画:
<transition name="AA" appear>//appear:页面加载完立即出现动画
<h1 v-show="">你好!</h1>
</transition>
.AA-enter-active{
animation:ff 0.5s linear;
}
.AA-leave-active{
animation: ff 0.5s linear reverse;//匀速 取反
}
@keyframes ff {
from{
transform: translateX(-100%);
}to{
transform: translateX(0px);
}
}
第二种方式:
.AA-enter,.AA-leave-to{
transform: translateX(-100%);
}
.AA-enter-active,.AA-leave-active{
transition: 0.5s linear;
}
/* 进入的终点、离开的起点 */
.AA-enter-to,.AA-leave{
transform: translateX(0);
}
包裹要过渡的元素
包裹多个元素,每个元素都要指定key
值。
<transition-group name="hello" appear>
<h1 v-show="!isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">!</h1>
</transition-group>
可以通过npm安装animate.css,使用第三方动画
vue脚手架配置代理–解决跨域请求问题
你的端口号是8080,要请求服务器5000的资源,会因为跨域报错。这需要代理服务器,你向代理发送8080请求,代理帮你发送5000请求。
开启代理服务器,在vue.config.js中添加配置:
devServer:{
proxy:"http://localhost:5000"//把请求发给5000
}
配置多个代理:
devServer: {
proxy: {
'/api1': {// 匹配所有以 '/api1'开头的请求路径
target: 'http://localhost:5000',// 代理目标的基础路径
changeOrigin: true,//伪装源头
pathRewrite: {'^/api1': ''}//路径重写,把api1去掉,再代理
},
'/api2': {
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: {'^/api2': ''}
}
}
}
插槽–让父组件向子组件插入html结构。就是挖个坑,让使用者填。
父组件中使用:
<Category>
<template slot="center">
<div>html结构1</div>
</template>
//v-slot:footer只能在template写
<template v-slot:footer>
<div>html结构2</div>
</template>
</Category>
子组件Category中定义:
<template>
<div>
<!-- 定义插槽 -->
<slot name="center">...</slot>
<slot name="footer">插槽默认内容...</slot>
</div>
</template>
作用域插槽–数据在组件自身,结构由使用者定。应该比较少用
父组件中:
<Category>
<template scope="scopeData">
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
子组件中:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
data() {
return {
games:['红色','穿越']
}
},
}
</script>
**splice() **–用于添加或删除数组中的元素,会改变原始数组。
array.splice(2)//删除索引2及以后的元素,返回删除元素的数组。
array.splice(2,1)//删除索引2之后的一个数,即索引2
array.splice(2,0,8,9)//索引2的位置添加8,9,2被挤到后面
Vuex–插件,状态管理工具 组件之间共享数据时使用
vue2->vuex3 //版本对应
vue3->vuex4
配置:
//创建文件:src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//响应动作
const actions = {
//context上下文对象包含了commit方法
jia(context,value){
context.commit('JIA',value)
},
}
//修改state的数据
const mutations = {
JIA(state,value){
state.sum += value
}
}
//保存数据
const state = {
sum:0
}
export default new Vuex.Store({
actions,
mutations,
state
})
//在main.js中创建vm时传入store配置项
import store from './store'
new Vue({
el:'#app',
render: h => h(App),
store
})
使用:
读取vuex中的数据:$store.state.sum
修改vuex中的数据:$store.dispatch('action中的方法名',数据) 或 $store.commit('mutations中的方法名',数据)
<h1>{{$store.state.sum}}</h1>
<button @click="aa">+</button>
methods: {
bb(){
this.$store.dispatch('jia',1)
},
aa(){
this.$store.commit('JIA',1)
},
}
getters–将state中的数据额外加工,满足个别组件的要求
使用:
<h3>放大10倍为:{{$store.getters.bigSum}}</h3>
配置:
//文件src/store/index.js
.....
const getters = {
bigSum(state){
return state.sum*10
}
}
vue的四个map方法
模版引用数据时,需要写长代码:<h1>{{$store.state.num}}</h1>
有解决办法:用计算属性
需要亲自写计算属性,仍然不便,而map方法可以提供更好的帮助,映射对应的数据为计算属性。
原代码:
<h1>{{sum}}</h1>
<h3>放大10倍为:{{bigSum}}</h3>
<button @click="in">+</button>
<button @click="inOdd"></button>
computed:{
sum(){
return this.$store.state.sum
},
bigSum(){
return this.$store.getters.bigSum
}
}
methods: {
in(){
this.$store.commit('JIA',this.n)
},
inOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
}
使用mapState、mapGetters、mapActions和mapMutations:
<h1>{{sum}}</h1>
<h3>放大10倍为:{{bigSum}}</h3>
<button @click="increment(n)">+</button>//加括号传参数
<button @click="incrementOdd(n)"></button>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
computed:{
// ...mapState({sum:'sum',school:'school'})//(对象写法)
...mapState(['sum','school']),//(数组写法)
...mapGetters(['bigSum'])
}
methods: {
...mapMutations({in:'JIA',}),
...mapActions({inOdd:'jiaOdd',})//与actions对话
}
vuex模块化+命名空间–明确数据分类
配置 修改store里的index.js:
//用于计算的数据
const countAbout = {
namespaced:true,//开启命名空间
state:{},
mutations: { ... },
actions: { ... },
getters: {...}
}
//用于人员相关的数据
const personAbout = {
namespaced:true,//开启命名空间
state:{ ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
countAbout,
personAbout
}
})
使用: //要注意数据属于哪个模块
computed:{
...mapState('countAbout',['sum','school']),
...mapGetters('countAbout',['bigSum'])
}
methods: {
...mapMutations('countAbout',{in:'JIA',}),
...mapActions('countAbout',{inOdd:'jiaOdd',})
}
路由–
配置:
npm i vue-router
import VueRouter from 'vue-router'
const router = new VueRouter({
routes:[
{
path:'/about',
component:About
children:[ //children 配置子级路由
{
path:'news', //news前面不加斜杠
name:'news' //给路由命名
component:News
},
]
},
]
})
export default router
注意点:
路由组件放在pages文件夹,一般组件放在components文件夹。
切换后,原组件默认被销毁。
每个组件有$route属性,存储自己的路由信息。
整个应用只有一个router,可通过组件的$router获取。
命名路由–简化路由的跳转
<!--简化前,需要写完整的路径 -->
<router-link to="/about/news">跳转</router-link>
<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'news'}">跳转</router-link>
路由的query参数– /ˈkwɪəri/
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link
:to="{
name:'hello',
query:{
id:666,
title=你好
}
}"
>跳转</router-link>
<!-- to的字符串写法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
接收参数:
$route.query.id
路由的params参数
配置 必须声明接收params参数:
routes:[
{
path:'/about',
component:About
children:[
{
path:'news/:id/:title', //使用占位符声明
name:'news'
component:News
},
]
},
]
传递:
<router-link
:to="{
name:'news',
params:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
接收:
$route.params.id
路由的props参数– /prɒps/
配置:
children:[
{
path:'news/:id/:title', //使用占位符声明
name:'news'
component:News
//props值为布尔值true,把收到的params参数通过props传给组件
props:true
//props值为函数,每一组key-value都通过props传给组件
//props(route){
return {
id:route.query.id,
title:route.query.title
}
}
},
]
传递:
<router-link
:to="{
name:'news',
params:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
接收:
<li>{{id}}</li>
props:['id','title']
编程式路由导航–不借助<router-link>
实现路由跳转
this.$router.push({//默认,追加历史记录
name:'news',
params:{
id:xxx
}
})
this.$router.replace({//替换当前记录
name:'news',
params:{
id:xxx
}
})
this.$router.forward() //前进
this.$router.back() //后退
this.$router.go() //可前进也可后退,-1:后退1页,3:前进3页
keep-alive缓存路由组件–让不展示的路由组件保持挂载
<router-link active-class="active" to="/home/news">News</router-link>
<router-link active-class="active" to="/home/message">Message</router-link>
<keep-alive include="News">
<router-view></router-view>//是一个容器,展示子路由
</keep-alive>
两个新的生命周期钩子–组件缓存后,有失活和激活两种状态
//路由组件被激活时触发
activated() {
this.timer =...
},
//路由组件失活时触发
deactivated() {
clearInterval(this.timer)
}
路由守卫–对路由进行权限控制
配置:router/index.js
{ //meta可以自己定义一些数据
name:'news',
path:'news',
component:News,
meta:{isAuth:true,title:'新闻'}
},
//全局前置守卫:初始化时执行、每次路由切换前执行
router.beforeEach((to,from,next)=>{
console.log('beforeEach',to,from)
if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
if(...){
next() //放行
}else{
}
}else{
next() //放行
}
})
//全局后置守卫:初始化时执行、每次路由切换后执行
router.afterEach((to,from)=>{
if(to.meta.title){
document.title = to.meta.title //修改网页的title
}
})
独享守卫: 进入之前调用
beforeEnter(to,from,next){
if(to.meta.isAuth){
if(...){
next() //放行
}else{
}
}else{
next() //放行
}
}
组件内守卫:
//进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
},
//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {
}
路由器的两种工作模式
1. url的 #及其后面的内容就是hash值。
2. hash值不会包含在 HTTP 请求中,即不会带给服务器。
3. hash模式:
地址中#号不美观
地址地址会被标记为不合法。
兼容性较好。
4. history模式:
地址美观 。
兼容性和hash模式相比略差。
应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。