1. watch 与 computed 的巧妙结合
如上图, 一个简单的列表页面.
你可能会这么做:
- created(){
- this.fetchData()
- },
- watch: {
- keyword(){
- this.fetchData()
- }
- }
如果参数比较多, 比如上图
关键字筛选,
区域筛选,
设备 ID 筛选,
分页数,
每页几条数据,
可能会是这样:
- data(){
- return {
- keyword:'',
- region:'',
- deviceId:'',
- page:1
- }
- },
- methods:{
- fetchData(paramrs={
- keyword:this.keyword,
- region:this.region,
- deviceId:this.deviceId,
- page:this.page,
- }){
- this.$http.get("/list",paramrs).then("do some thing")
- }
- },
- created(){
- this.fetchData()
- },
- watch: {
- keyword(data){
- this.keyword=data
- this.fetchData()
- },
- region(data){
- this.region=data
- this.fetchData()
- },
- deviceId(data){
- this.deviceId=data
- this.fetchData()
- },
- page(data){
- this.page=data
- this.fetchData()
- },
- requestParams(params){
- this.fetchData(params)
- }
- }
不过这么写, 明显有问题, 主要是 watch 了很多参数, 而且函数的处理都差不多, 可以修改一下, 通过 methods 处理
- data(){
- return {
- keyword:'',
- region:'',
- deviceId:'',
- page:1
- }
- },
- methods:{
- paramsChange(paramsName,paramsValue){
- this[paramsName]=paramsValue
- this.fetchData()
- },
- fetchData(paramrs={
- keyword:this.keyword,
- region:this.region,
- deviceId:this.deviceId,
- page:this.page,
- }){
- this.$http.get("/list",paramrs).then("do some thing")
- }
- },
- created(){
- this.fetchData()
- }
当然这么写, 需要在模板里面每个参数 change 的地方绑定事件, 并传递参数值, 比如分页 change 时:
<el-pagination
layout="total, prev, pager, next, jumper"
:total="total"
prev-text="上一页"
next-text="下一页"
@current-change="paramsChange('page',$event)"
>
</el-pagination>
相比上面的各种 watch, 代码明显少了很多, 但是还有一个问题, 那就是要在 template 的很多地方绑定 change 事件.
最后, 当然是使用我们重点推荐的 computed + watch 了
- data(){
- return {
- keyword:'',
- region:'',
- deviceId:'',
- page:1
- }
- },
- computed:{
- requestParams() {
- return {
- page: this.page,
- region: this.region,
- id: this.deviceId,
- keyword: this.keyword
- }
- }
- },
- methods:{
- fetchData(paramrs={
- keyword:this.keyword,
- region:this.region,
- deviceId:this.deviceId,
- page:this.page,
- }){
- this.$http.get("/list",paramrs).then("do some thing")
- }
- },
- watch: {
- requestParams: {
- handler: 'fetchData',
- immediate: true
- }
- },
通过增加一个 computed 属性, watch 这个属性并设置 immediate 为 true, 无需再手动绑定事件, 相比之上的方法都要简洁. 当然, 缺点就是对性能稍微有些影响, 不过问题不大.
2. 使用 mixin 提取公共部分
很多列表页其实使用的很多属性都是一样的, 比如
分页 page
数量 size
搜索关键 字 keyword
表格数据 tableData
这些公共的部分其实可以通过 mixin 来提取出来
- /**
- * mixin/table.js
- */
- export default {
- data() {
- return {
- keyword: '',
- requestKeyword: '',
- pages: 1,
- size: 10,
- total: 0,
- tableData: []
- }
- }
- }
在要用到的页面
- import mixin from '@/mixin/table'
- export default {
- mixins: [mixin],
- data() {
- return {
- selectRegion: '',
- selectDevice: '',
- deviceList: [],
- }
- }
- /* 其他代码 */
- ...
3. 自动注册全局组件
正常情况下, 我们需要使用一个我们自己封装的组件时, 需要先引入, 再注册, 最后才能在 template 模板中使用.
- <template>
- <all-region :selectRegion="selectRegion" @region-change="selectRegion=$event"/>
- </template>
- <script>
- import AllRegion from './baseButton'
- export default {
- components: {
- AllRegion,
- }
- }
- </script>
当有多个页面需要用到这些组件时, 那么就需要在每个需要的页面重复这些步骤.
为了简化这些步骤, 可以考虑把这些组件作为全局组件来使用, 这样每个页面需要时, 就可以直接使用了.
不过还有一个问题, 那就是需要我们手动的全局注册
- .
- /* main.js */
- import Component1 from '@/component/compenent1'
- import Component2 from '@/component/compenent2'
- import Component3 from '@/component/compenent3'
- vue.component('component1', Component1)
- Vue.component('component2', Component2)
- Vue.component('component3', Component3)
当组件多了以后, 手动注册也变得繁琐起来, 可以通过 require.context() 实现自动注册组件.
- /**
- * main.js
- * 读取 componetns 下的 vue 文件并自动注册全局组件
- */
- const requireComponent = require.context('./components', false, /\.vue$/)
- requireComponent.keys().forEach(fileName => {
- const componentConfig = requireComponent(fileName)
- const componentName = fileName.replace(/^\.\//, '').replace(/\.vue/,'')
- Vue.component(componentName, componentConfig.default || componentConfig)
- })
4. 自动注册 vuex 模块
之前我们是这么注册 vuex 模块的
- /* module.js */
- import alarm from './modules/alarm'
- import history from './modules/history'
- import factory from './modules/factory'
- import contact from './modules/contact'
- import company from './modules/company';
- import deviceManage from './modules/device-manage'
- import deviceModel from './modules/device-model'
- import deviceActivation from './modules/device-activation'
- import user from './modules/user'
- import role from './modules/role'
- import setAlarm from './modules/setAlarm'
- import factoryMode from "./modules/factoryMode";
- import ScreenDeviceWatch from './modules/screen-device-watch'
- import ScreenDeviceForecast from './modules/screen-device-forecast'
- export default {
- alarm,
- company,
- deviceManage,
- deviceModel,
- user,
- factory,
- contact,
- deviceActivation,
- history,
- role,
- setAlarm,
- factoryMode,
- ScreenDeviceWatch,
- ScreenDeviceForecast,
- }
- /* index.js */
- import Vue from 'vue'
- import Vuex from 'vuex'
- import state from './state'
- import getters from './getters'
- import modules from './modules'
- import actions from './actions'
- import mutations from './mutations'
- Vue.use(Vuex)
- export default new Vuex.Store({
- state,
- getters,
- mutations,
- actions,
- modules
- })
可以发现每个模块都要我们手动导入, 然后加入到 module 里面, 如此重复. 当模块不多还好, 假如项目大了, 有 50 个模块, 那就得要做很多重复的工作.
跟注册组件一样, 我们还是利用 require.context 来实现.
- /**
- * 读取./modules 下的所有 js 文件并注册模块
- */
- const requireModule = require.context('./modules', false, /\.js$/)
- const modules = {}
- requireModule.keys().forEach(fileName => {
- const moduleName = fileName.replace(/(\.\/|\.js)/g, '')
- modules[moduleName] = {
- namespaced: true,
- ...requireModule(fileName).default
- }
- })
- export default modules
- /* index.js */
- import Vue from 'vue'
- import Vuex from 'vuex'
- import modules from './modules'
- Vue.use(Vuex)
- export default new Vuex.Store({
- state,
- getters,
- mutations,
- actions,
- modules
- })
本文参考自油管上某个国外大神的公开演讲视频, 学习了一下觉得很不错, 所以在项目中也使用了这些不错的技巧. 趁周末有空, 写个博客记录一下.
来源: https://www.cnblogs.com/zhengrunlin/p/9164951.html