Vue功能实现和使用技巧
汇总记录前端开发时,使用 Vue 框架遇到的功能实现和开发技巧。
Vue 动态组件使用
动态组件功能用于在不同组件之间进行动态切换,可以通过 Vue 的 <component>
元素加一个特殊的 is attribute 来实现
// `currentComponent` 改变时显示的组件同时改变 |
- v-show,v-if,:is 之间的区别
v-show
会同时加载两个组件,两个组件的生命周期都会触发,会造成不必要的性能浪费,而且切换的时候不会再创造挂载一次,无法重新渲染。v-if
不会造成同时加载两个组件,但 v-if 每次切换都会创造挂载一次,如果没有重新渲染的需要,会造成性能浪费。:is
可以通过 keep-alive 标签缓存,被该标签包裹的组件会被缓存下来,每次点击都不会重新渲染,避免了重渲染导致的性能问题。include
和 exclude
属性也允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示。
<!-- 逗号分隔字符串 --> |
动态路由匹配
动态路由用于把某种模式匹配到的所有路由,全都映射到同个组件,可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果。一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params
,可以在每个组件内使用。
const router = new VueRouter({ |
页面跳转和导航
定义链接实现声明式导航
<router-link :to="...">
内部调用 router.push
方法实现页面导航
<router-link :to="{name: 'detail', params: {name: 1}}"> xxx </router-link> |
- 可以使用
this.$route.params
或this.$route.params
获取路由参数。
- router 实例实现编程式导航
在 Vue 实例内部,可以通过 $router
访问路由实例,可以调用 this.$router.push
方法,向 history 栈添加一个新的记录,点击浏览器后退按钮时也可以回到之前的 URL。
params 相对应的是 name, query 相对应的是 path
// 字符串 |
router.replace('')
跳转页面会替换掉原有的 history 记录router.go(n)
在 history 记录中前进或后退多少步
keep-alive 网页性能优化
keep-alive 主要用于保留组件状态或避免重新渲染 DOM 导致性能降低,通常都会在 app.vue
的 <router-view/>
外面加一层 <keep-alive>
<keep-alive> |
这样做也会导致一些问题,当组件的值更新后组件没有被重新渲染,做到动态显示需要使用额外生命周期函数 activated
进入页面会执行 mounted 和 activated,当修改值后再次进入首页不会再执行 mounted 触发新的数据请求,但是 activated 会继续执行。可以在 activated 函数中判断新数据和前一次显示是否相同,如果不同再次触发 ajax 数据请求。
mounted () { |
在路由更新后页面由于 keep-alive 的缓存不会执行 mounted 触发刷新,需要设置路由的 key 值,在每次进入页面时比较路由名称,若不相同则刷新页面。
/*App.vue*/ |
Vuex 数据防刷新丢失
引入 vuex-persist 插件将状态保存至 cookie 或者 localStorage 中,刷新后数据不丢失。
import VuexPersistence from 'vuex-persist' |
自定义指令避免误触和多次点击
使用 Vue.directive 自定义防误触指令
import Vue from 'vue' |
制作可复用组件
复用组件需要在样式和功能上做到继承和迭代,是在系统整体设计时抽象出的组件,多为布局组件,不涉及详细的功能实现。组件需要做到高内聚低耦合,组件内独立交互,功能受控于组件本身。
// 按钮组件抽象,样式设置为外部继承 cname,和内部自定义 button,留出按钮名称 title 和 <slot> 插槽作为具体内容的补充空间 |
上传文件功能
使用 element-ui 的 upload 功能实现图片展示,上传和读取,on-change 触发文件状态改变时的钩子,调用上传照片 api 将照片数据传递到后台;on-preview 用于显示已上传的图片的缩略图;传递多个文件时文件列表存储在 file-list 中。
<el-upload |
// 获取文件信息 |
若上传 base64 位图片需要进行转码之后调用 api 上传:
// 图片转base64 |
Vuex 监听状态变更
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
state: { |
兄弟组件,跨多层组件之间事件传递方法
使用集中的事件处理器,建立一个空的 vue 实例实现了事件分发接口。在初始化 web app 的时候,给 data 添加一个 eventhub 的空 vue 对象。然后在组件中,可以使用 $emit,$on,$off 分别来分发、监听、取消监听事件。
new Vue({ |
或者在初始化 Vue 对象之前给原生对象增加 eventHub 属性,这样在组件内部 就可以直接调用$eventHub
对象。Vue.prototype.$eventHub= Vue.prototype.$eventHub || new Vue()
发送数据:this.$root.eventHub.$emit('YOUR_EVENT_NAME', yourData)
接收数据:this.$root.eventHub.$on('YOUR_EVENT_NAME', yourData)
销毁数据:this.$root.eventHub.$off()
// 在组件销毁时需要结束绑定,使用 $off
方法
// 发送数据 |
// 接收数据 |
回到顶部功能
使用 element-ui 中提供的功能实现:
<el-backtop |
也可以使用 better-scroll 插件实现,通过监听下拉时 y 轴的移动距离显示上拉按钮,点击后触发返回顶部事件。
// 回到开头 |
element-ui 按需引入
通过借助 babel-plugin-component
或直接修改 .babelrc
文件,我们可以只引入需要的组件,以达到减小项目体积的目的。
引入插件:npm install babel-plugin-component -D
修改 babel 配置文件:
"plugins": [ |
在 src 文件夹中 plugins 文件夹内新建一个 element.js 文件,导入需要的组件
// 导入自己需要的组件 |
最后在 main.js 中引入 element.js 文件 import './plugins/element.js'
表单设置日期限制
element-ui 支持在创建表单时使用规则校验,可以在校验中自定义校验规则。
在日期选择时需要实现截止日期必须大于等于开始日期,在 vue 组件中定义表单数据和校验规则并在 endDate 中自定义校验规则 checkEnd
:
data () { |
在 data 中设置变量 checkEnd
来实现校验规则,校验错误时返回提示:
data () { |
表单身份证校验
通过自定义表单校验规则进行身份证的校验,新建 idValidate.js 文件实现身份证校验算法。
let checkId = (rule, value, callback) => { |
/* idValidate.js */ |
持续拉取后台数据
实现后台请求数据时不一次性返回,需要返回一部分就显示一部分。setInterval()
方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
methods: { |
添加和删除属性(不再使用)
在 vue 中,直接使用赋值语句无法触发视图页面更新;对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 set 和 delete 修改 property 来触发视图更新。
Vue.set( target, propertyName/index, value )
参数:
{Object | Array} target
{string | number} propertyName/index
{any} value
还可以使用 vm.$set 实例方法,是全局 Vue.set 方法的别名
Vue.delete( target, propertyName/index )
参数:
{Object | Array} target
{string | number} propertyName/index
还可以使用 vm.$delete 实例方法
vue 2.x 之后,Vue.set 和 Vue.delete 在实例上将不再起作用。现在都强制在实例的 data 选项中声明所有顶级响应值,通过改变 data 值实现相应。
其它注意事项
监听组件原生事件
@click.native=
可以在子组件监听根元素的原生事件,不需要通过$emit
事件ref 属性
给 DOM 元素或子组件注册引用信息,引用信息将会注册在父组件的$refs
对象上,如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。
通过this.$refs.ref
访问 dom 节点或组件实例(data)render: h => h(App)
h 作为 createElement 的别名是 Vue 生态系统中的一个通用惯例。它来自单词hyperscript
,这个单词通常用在 virtual-dom 的实现中。hyperscript 本身指生成 HTML 结构的 script 脚本。 — Even Yourender: function (createElement) {
return createElement(App);
}
// h <- createElement
render: function (h) {
return h(App);
}
// ES6
render: h => h(App)webpack 打包后引用路径问题
config\index.js
中的 build 模块修改导出路径 assetsPublicPath 为./
,使 index.html 和 static 文件夹在同一级目录下面。module.exports = {
build: {
...
assetsPublicPath: './',
}
}es6 语法兼容问题
build\webpack.base.conf.js
中的 entry 模块加入babel-polyfill
,让程序在打包时同时兼容低版本的浏览器。
vue3 版本中在自建的 vue.config.js 中添加 webpack config,将 entry 定义为@babel/polyfill
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: ['babel-polyfill', './src/main.js']
},
// entry: {
// app: './src/main.js',
// "babel-polyfill": "babel-polyfill"configureWebpack: (config) => {
if (process.env.NODE_ENV === 'production') {
return {
// 解决浏览器兼容ES6
entry: {
main: ['@babel/polyfill'],
}
...
}
}
}json 转换(重要)
vuex 里将状态保存到缓存中,会用到 json 转换,我们保存的状态都是数组,而 localStorage 只支持字符串
将数组传递到后台时也需要使用 JSON.stringify() 转换为字符串格式,回传时再转换为数组JSON.stringify(state.dataList) // array -> string
JSON.parse(window.localStorage.getItem('dataList')) // string -> arrayv-for 参数顺序变更
vue2.x 中,当包含 index 时,之前遍历数组时的参数顺序是(index, value)
。现在是(value, index)
,来和 JavaScript 的原生数组方法 (例如 forEach 和 map) 保持一致。
当包含 property 名称/key 时,之前遍历对象的参数顺序是(name, value)
。现在是(value, name)
,来和常见的对象迭代器 (例如 lodash) 保持一致。箭头函数
箭头函数的 this 在函数创建期间(普通函数在执行时绑定)完成绑定,this 指向该箭头函数被声明时所在的作用域对象。
箭头函数不能作为构造函数,没有 arguments,不能作为生成器函数。数组去重
Set 是无序的类数组数据类型,有相同的 key 和 value,无重复数值,可以创建 Set 实例进行数组去重newArr = [...new Set(arr)]
参考资料:
https://router.vuejs.org/zh/guide/essentials/navigation.html
https://vuex.vuejs.org/zh/
https://better-scroll.github.io/docs/zh-CN/
https://element.faas.ele.me/#/zh-CN/
https://cn.vuejs.org/v2/guide/migration.html
https://github.com/axios/axios
https://juejin.cn/post/6844903613609803783
- 本文链接:https://hyqskevin.github.io/2020/11/10/vue-notes/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!