sgg
自定义指令
第一个参数是真实dom
,第二个参数是相关参数
就算只是name变了,模板也会重新渲染,也就是big会再执行
注意操作时机
坑
指令名big-name
这种的话
所有指令里的this
指向window
动画效果
CSS animation 属性
过渡效果 Vue文档
{width=38%}
多个元素过渡
集成第三方动画 Animate.css
配置代理服务器 vue.config.js配置官方文档
方式一:只能配置一个代理,且不能灵活控制到底走不走代理转发(比如代理有的就不再转发给请求服务器了)
举例:8080自己 代理服务器8080 请求服务器5000
方式二:要走代理加前缀
全局前置路由守卫
优化,给路由标记是否需要权限校验
全局后置路由守卫
路由独享守卫(只有前置没有后置),需要可以与全局后置路由守卫配合使用
组件内路由守卫 注意是通过路由规则
Element UI 按需引入
新版vue-cli的babel.config.js
其实是以前的.babelrc
【配置了这个东西后,框架就能自动分析引入样式了,所以此时不要再引入全部样式了】
注意是按照官方文档的东西追加
进去,不是直接复制粘贴
报错解决
Vue3
Vue 2.0 响应式
Vue 2.0 监测数据变化的原理
Vue.set
只能给data里的某个属性追加属性,不能直接给data追加属性
用数组的索引直接修改数组元素,Vue监测不到你修改数组了
给对象中后追加属性,如果需要做响应式处理,则需使用Vue.set()
或者vm.$set()
Vue3.0的响应式
-
实现原理:
-
通过Proxy(代理): 拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。
-
通过Reflect(反射): 对源对象的属性进行操作。
-
MDN文档中描述的Proxy与Reflect:
new Proxy(data, {
// 拦截读取属性值
get (target, prop) {
return Reflect.get(target, prop)
},
// 拦截设置属性值或添加新属性
set (target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty (target, prop) {
return Reflect.deleteProperty(target, prop)
}
})
proxy.name = 'tom'
toRef
,toRefs
其它 Composition API
1.shallowReactive 与 shallowRef
- shallowReactive:只处理对象最外层属性的响应式(浅响应式)。
- shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。
- 什么时候使用?
- 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
- 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef。
2.readonly 与 shallowReadonly
- readonly: 让一个响应式数据变为只读的(深只读)。
- shallowReadonly:让一个响应式数据变为只读的(浅只读)。
- 应用场景: 不希望数据被修改时。
3.toRaw 与 markRaw
- toRaw:
- 作用:将一个由
reactive
生成的[HTML_REMOVED]响应式对象[HTML_REMOVED]转为[HTML_REMOVED]普通对象[HTML_REMOVED]。 - 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
- markRaw:
- 作用:标记一个对象,使其永远不会再成为响应式对象。
- 应用场景:
- 有些值不应被设置为响应式的,例如复杂的第三方类库等。
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
4.customRef
-
作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
-
实现防抖效果:
<template>
<input type="text" v-model="keyword">
<h3>{{keyword}}</h3>
</template>
<script>
import {ref,customRef} from 'vue'
export default {
name:'Demo',
setup(){
// let keyword = ref('hello') //使用Vue准备好的内置ref
//自定义一个myRef
function myRef(value,delay){
let timer
//通过customRef去实现自定义
return customRef((track,trigger)=>{
return{
get(){
track() //告诉Vue这个value值是需要被“追踪”的
return value
},
set(newValue){
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue
trigger() //告诉Vue去更新界面
},delay)
}
}
})
}
let keyword = myRef('hello',500) //使用程序员自定义的ref
return {
keyword
}
}
}
</script>
5.provide 与 inject
-
作用:实现祖与后代组件间通信
-
套路:父组件有一个
provide
选项来提供数据,后代组件有一个inject
选项来开始使用这些数据 -
具体写法:
-
祖组件中:
setup(){
......
let car = reactive({name:'奔驰',price:'40万'})
provide('car',car)
......
}
- 后代组件中:
setup(props,context){
......
const car = inject('car')
return {car}
......
}
6.响应式数据的判断
- isRef: 检查一个值是否为一个 ref 对象
- isReactive: 检查一个对象是否是由
reactive
创建的响应式代理 - isReadonly: 检查一个对象是否是由
readonly
创建的只读代理 - isProxy: 检查一个对象是否是由
reactive
或者readonly
方法创建的代理
Vue 3.0 变化
1.全局API的转移
-
Vue 2.x 有许多全局 API 和配置。
-
例如:注册全局组件、注册全局指令等。
//注册全局组件
Vue.component('MyButton', {
data: () => ({
count: 0
}),
template: '<button @click="count++">Clicked {{ count }} times.</button>'
})
//注册全局指令
Vue.directive('focus', {
inserted: el => el.focus()
}
-
Vue3.0中对这些API做出了调整:
-
将全局的API,即:
Vue.xxx
调整到应用实例(app
)上2.x 全局 API( Vue
)3.x 实例 API ( app
)Vue.config.xxxx app.config.xxxx Vue.config.productionTip [HTML_REMOVED]移除[HTML_REMOVED] Vue.component app.component Vue.directive app.directive Vue.mixin app.mixin Vue.use app.use Vue.prototype app.config.globalProperties
2.其他改变
-
data选项应始终被声明为一个函数。
-
过度类名的更改:
-
Vue2.x写法
.v-enter,
.v-leave-to {
opacity: 0;
}
.v-leave,
.v-enter-to {
opacity: 1;
}
- Vue3.x写法
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.v-leave-from,
.v-enter-to {
opacity: 1;
}
-
移除作为 v-on 的修饰符,同时也不再支持
config.keyCodes
-
移除
v-on.native
修饰符 -
父组件中绑定事件
<my-component
v-on:close="handleComponentEvent"
v-on:click="handleNativeClickEvent"
/>
- 子组件中声明自定义事件
<script>
export default {
emits: ['close']
}
</script>
- 移除过滤器(filter)
过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是 “只是 JavaScript” 的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。
- ......
前端工程化
早期的前端工程化解决方案:
- grunt( https://www.gruntjs.net/ )
- gulp( https://www.gulpjs.com.cn/ )
目前主流的前端工程化解决方案:
- webpack( https://www.webpackjs.com/ )
- parcel( https://zh.parceljs.org/ )
webpack 中的插件
最常用的webpack 插件有如下两个:
webpack-dev-server
- 类似于 node.js 阶段用到的 nodemon 工具
- 每当修改了源代码,webpack 会自动进行项目的打包和构建
html-webpack-plugin
- webpack 中的 HTML 插件(类似于一个模板引擎插件)
- 可以通过此插件自定制 index.html 页面的内容
- 通过 html-webpack-plugin 插件,将 src 目录下的 index.html 首页,复制到项目根目录中一份
凡是修改了 webpack.config.js 配置文件,或修改了 package.json配置文件,必须重启实时打包的服务器,否则最新的配置文件无法生效
Source Map 的最佳实践
- 开发环境下:
- 建议把
devtool
的值设置为eval-source-map
- 好处:可以精准定位到具体的错误行
- 建议把
- 生产环境下:
- 建议关闭 Source Map 或将
devtool
的值设置为nosources-source-map
- 好处:防止源码泄露,提高网站的安全性
- 建议关闭 Source Map 或将
建议大家使用 @ 表示 src 源代码目录,从外往里查找;不要使用 ../ 从里往外查找
知道原理即可,以后不用手动配置
// import msg from '../../msg'
import msg from '@/msg.js'
VUE基础入门
组件的 props
props是只读的,要想修改 props 的值,可以把 props 的值转存到 data 中,因为 data 中的数据都是可读可写的
当然设置了required为true后(required选项,将属性设置为必填项,强制用户必须传递属性的值),就不要定义default属性了
{ width=71%}
组件之间的样式冲突问题
- vue 为 style 节点提供了
scoped 属性
,从而防止组件之间的样式冲突问题
- 如果给当前组件的style节点添加了scoped属性,则当前组件的样式对其子组件是不生效的。
如果想让某些样式对子组件生效,可以使用 /deep/ 深度选择器
生命周期&数据共享
组件之间的数据共享
EventBus 的使用步骤
- 创建
eventBus.js
模块,并向外共享一个Vue 的实例对象
- 在数据
发送方
,调用bus.$emit('事件名称', 要发送的数据)
方法触发自定义事件
- 在数据
接收方
,调用bus.$on('事件名称', 事件处理函数)
方法注册一个自定义事件
购物车案例
- APP.vue里算全选按钮应不应该选上,然后传给子组件footer,让子组件的全选按钮选上。
DAY06
插槽
具名插槽
为具名插槽提供内容
- 简写:
v-slot:
替换为字符#
作用域插槽
使用作用域插槽
v-slot只能用在组件或者template里
ESLint
了解.eslintrc.js配置文件中的rules规则
配置VSCode
{
//ESLint插件的配置
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"prettier.configPath": "C:\\Users\\BOO\\.prettierrc",
"eslint.alwaysShowStatus": true,
"prettier.trailingComma": "none",
"prettier.semi": false,
//每行文字个数超过此限制将会被迫换行
"prettier.printWidth": 300,
//使用单引号替换双引号
"prettier.singleQuote": true,
"prettier.arrowParens": "avoid",
//设置.vue文件仲,HTML代码的格式化插件
"vetur.format.defaultFormatter.html":"js-beautify-html",
"vetur.ignoreProjectWarning":true,
"vetur.format.defaultFormatterOptions":{
"prettier": {
"trailingComma":"none",
"semi":false,
"singleQuote":true,
"arrowParens":"avoid",
"printWidth":300
},
"js-beautify-html": {
"wrap_attributes":false
}
},
"files.autoSave": "onFocusChange",
"window.zoomLevel": 0,
"editor.formatOnType": true,
"editor.formatOnSave": true,
"cssrem.rootFontSize": 75,
"workbench.colorTheme": "Default Light+",
"explorer.confirmDelete": false,
"editor.tabSize": 2
}
把axios挂载到Vue的原型上并配置请求根路径
- 但是这样不利于API接口的复用,比如需要多次axio请求图书列表