项目七遇到的知识点

一、vue3.0写法

  • 这次项目使用vue3.0来写,写的过程中突然发现差别挺大的,感觉不会写vue了,所以总结总结。。。

  • This is an 官网地址:

1、安装vue-cli 3.0

  • npm i @vue/cli -g

2、运行

  • npm run serve

3、TypeScript的支持

  • 遇到的vue3.0写法

    import { Watch, Component, Vue, Emit, Prop } from "vue-class-decorator";
    // 没有组件
    @component

    // 有组件
    // import children from "./components/children.vue";
    // @component({ components:{children} })

    export default class MyChildren extends Vue{
    username = ""; // 名字
    //userId 父子之间传值,必传默认是null
    @Prop({ type: String, required: true, default: null})
    userId: string;
    @Emit("changeChildren")
    changeChildren(){}

    created(){}
    mounted(){}
    // 方法
    cancel() {
    // 调用自定义函数
    this.changeChildren()
    }
    }

  • 以下是我百度看到的,写的非常详细

  • 在3.0版本中,选择启动typescript语法后,vue组件的书写格式有特定的规范。

  • 示例代码

百度查看的结果
 
     import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from "vue-property-decorator"
	const s = Symbol('baz')
	@Component
	export class MyComponent extends Vue {
	  @Emit()
	  addToCount(n: number){ this.count += n}
	  @Emit('reset')
	  resetCount(){ this.count = 0 }
	  @Inject() foo: string
	  @Inject('bar') bar: string
	  @Inject(s) baz: string
	  @Model('change') checked: boolean
	  @Prop()
	  propA: number
	  @Prop({ default: 'default value'})
	  propB: string
	  @Prop([String, Boolean])
	  propC: string | boolean
	  @Provide() foo = 'foo'
	  @Provide('bar') baz = 'bar'
	  @Watch('child')
	  onChildChanged(val: string, oldVal: string) { }
	  @Watch('person', { immediate: true, deep: true})
	  onPersonChanged(val: Person, oldVal: Person){}
	}
  
以上代码相当于
 
  const s = Symbol("baz");
  export const myComponent = Vue.extend({
    name: "MyComponent",
    inject: {
      foo: "foo",
      bar: "bar",
      [s]: s
    },
    model: {
      prop: "checked",
      event: "change"
    },
    props: {
      checked: Boolean,
      propA: Number,
      propB: {
        type: String,
        default: "default value"
      },
      propC: [String, Boolean]
    },
    data() {
      return {
        foo: "foo",
        baz: "bar"
      };
    },
    provide() {
      return {
        foo: this.foo,
        bar: this.baz
      };
    },
    methods: {
      addToCount(n) {
        this.count += n;
        this.$emit("add-to-count", n);
      },
      resetCount() {
        this.count = 0;
        this.$emit("reset");
      },
      onChildChanged(val, oldVal) {},
      onPersonChanged(val, oldVal) {}
    },
    watch: {
      child: {
        handler: "onChildChanged",
        immediate: false,
        deep: false
      },
      person: {
        handler: "onPersonChanged",
        immediate: true,
        deep: true
      }
    }
  });
  

4、知识点

  • 选项/组合 provide/inject
  • @Provide 提供 / @inject注入

(1)、类型

  • provide: Object | () => Object
  • inject: Array |
  • 这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

(2)、示例


// 父级组件提供'foo'
var Provider = {
	provide: {
		foo: 'bar'
	}
}
// 子件注入'foo'
var Child = {
	inject: ['foo'],
	created() {
		console.log(this.f00) // bar
	}
}

(3)、vue-property-decorator

  • npm install --save vue-property-decorator /npm i -S vue-property-decorator

vue-property-decorator提供OO的风格Vue Component方便类型声明

vue-class-component 以class的模式写vue组件


vue class component 是vue官方出的
vue property decorator 是社区出的
其中vue class component 提供了vue component等等
vue property decorator深度依赖了vue class component扩展出了很多操作符@Prop @Emit @Inject等等 可以说是vue class component的一个超集
正常开发的时候 你只需要使用vue property decorator 中提供的操作符即可 不再从vue class component引入vue

二、相同页面点击不同按钮出现内容

新增和修改都是用同一个页面,希望点击各自的按钮跳转到页面时调用各自的接口

  • 效果图

  • 子组件


  • 父组件


    <add-role
    v-if="roleShow"
    :addId="addId"
    @addRole="addRole"
    >

  • 思路

  • 父子之间传值,点击修改的时候传newId,新增的时候不传默认是null,这样就可以在子组件里区分是新增页面还是修改页面

三、Element 默认勾选表格 toggleRowSelection

element type="selection" 我希望当我点击勾选框后第二次点击是选中的状态;
我只是为了实现内容,实际用到的要走接口

  • 效果图

1、子组件内容

(1)、html

(2)、样式内容

less

.table-mask {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0px;
    right: 0px;
    z-index: 9;
    overflow-x: hidden;
    overflow-y: scroll;
    background: rgba(0, 0, 0, 0.5);
    .table-main {
      position: absolute;
      left: 50%;
      top: 50%;
      margin-top: -200px;
      margin-left: -280px;
      width: 560px;
      padding: 20px;
      box-sizing: border-box;
      background: #fff;
    }
  }
	

(3)、js逻辑

ts实现

  import { Watch, Component, Vue, Emit, Prop } from "vue-class-decorator";
  @Component
  export default class ChangeTable extends Vue {
    $refs: {
      multipleTable: any;
    };
    tableData = [
      {
        id: 1,
        date: "2016-05-03",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄"
      },
      {
        id: 2,
        date: "2016-05-02",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄"
      },
      {
        id: 3,
        date: "2016-05-04",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄"
      },
      {
        id: 4,
        date: "2016-05-01",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄"
      },
      {
        id: 5,
        date: "2016-05-08",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄"
      },
      {
        id: 6,
        date: "2016-05-06",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄"
      },
      {
        id: 7,
        date: "2016-05-07",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄"
      }
    ];
    multipleSelection = [];
    @Emit("ChangeClick")
    ChangeClick(flag) {}
    @Prop({ type: Array, required: true })
    hasArray: any[];
    created() {
      this.InitData();
    }
    // 初始化
    InitData() {
      if (this.hasArray) {
        const indexList = []; // 存储交集的index,用来勾选状态
        this.hasArray.forEach(table => {
          this.tableData.forEach((item, index) => {
            if (table.id === item.id) {
              indexList.push(index);
            }
          });
        });
        this.$nextTick(() => {
          indexList.forEach(e => {
            this.$refs.multipleTable.toggleRowSelection(this.tableData[e], true);
          });
        });
      }
    }
    // 获取选中的值
    handleSelectionChange(val) {
      this.multipleSelection = val;
    }
    // 单击某一行数据时选中对应的复选框
    clickRow(row) {
      this.$refs.multipleTable.toggleRowSelection(row);
    }
    cancel() {
      this.ChangeClick(false);
    }
    submit() {
      this.ChangeClick({ flag: true, checked: this.multipleSelection });
    }
  }
	

2、父组件内容

html

<el-button
@click="handleTable"
type="primary"
>点击弹出表格
<my-table
v-if="isTableShow"
:hasArray="hasArray"
@ChangeClick="ChangeClick"
>

js

import myTable from "./components/table.vue";

@Component({
components: {
myTable
}
})
export default class ChangePassword extends Vue {
isTableShow = false;
hasArray = [];
handleTable() {
this.isTableShow = true;
}
ChangeClick(flag) {
if (flag) {
this.hasArray = flag.checked;
}
this.isTableShow = false;
}
}

3、知识点

  • 官网

(1)、toggleRowSelection

  • toggleRowSelection(row,selected)接收两个参数,row传递被勾选行的数据,selected设置是否选中
  • 调用toggleRowSelection这个方法需要获取真实dom所以需要注册ref来引用它。

(2)、row-click 点击行事件


// 单击某一行数据时选中对应的复选框
clickRow(row) {
  this.$refs.multipleTable.toggleRowSelection(row);
}

(3)、element ui tree 获取到选中节点

<el-tree
ref="tree"
:data="dataList"
:props="defaultProps"
node-key="Code"
:default-checked-keys="defaultId"
show-checkbox
@check-change="getChecked"
>

  • 方法

    getChecked(){
    this.$refs.tree.getCheckedNodes();
    }

其他

  • reserve-selection

  • 仅对 type=selection 的列有效,类型为 Boolean,为 true 则会在数据更新之后保留之前选中的数据(需指定 row-key)(默认false)

  • row-key

  • 行数据的 Key,用来优化 Table 的渲染;在使用 reserve-selection 功能与显示树形数据时,该属性是必填的。类型为 String 时,支持多层访问:user.info.id,但不支持 user.info[0].id,此种情况请使用 Function。

四、导出excel(下载excel)

  • 也要根据后端写的接口来,不一定适用所有的下载excel

  // 提取导出文件的文件扩展名(类型)
  const [, extName] = /filename=".*(\..*)";/.exec(
    res.headers["content-disposition"]
  );
  // 构造下载文件名的名字
  const fileName = new Date().getTime().toString() + (extName || "");


  // #region 进行下载
  const link = document.createElement("a");
  link.href = window.URL.createObjectURL(res.data);
  link.download = fileName;
  // 此写法兼容可火狐浏览器
  document.body.appendChild(link);
  const evt = document.createEvent("MouseEvents");
  evt.initEvent("click", false, false);
  link.dispatchEvent(evt);
  document.body.removeChild(link);
  // #endregion

五、数组中多条对象去重

数组去重
 
 const list1 = [
    {
      id: 1,
      name: "张三"
    },
    {
      id: 2,
      name: "李四"
    }
  ];
  const list2 = [
    {
      id: 1,
      name: "张三"
    },
    {
      id: 3,
      name: "王麻子"
    }
  ];
  const oldArray = [...list1, ...list2];
  console.log(oldArray);
  const newArray = [];
  for (let i = 0; i < oldArray.length; i++) {
    let flag = true;
    for (let j = 0; j < newArray.length; j++) {
      if (oldArray[i].id === newArray[j].id) {
        flag = false;
      }
    }
    if (flag) {
      newArray.push(oldArray[i]);
    }
  }
  console.log(newArray);
  
  • 打印效果

vue store存储commit和dispatch

  • this.$store.commit("toShowLoginDialog",true)
  • this.$store.dispatch('toShowLoginDialog',false)
  • 主要区别是
  • dispatch:含有异步操作,例如向后台提交数据,写法:this.$store.dispatch('mutations方法名',值)
  • commit:同步操作,写法:this.$store.commit('mutataions方法名',值)
posted @ 2019-05-16 11:36  不完美的完美  阅读(470)  评论(0)    收藏  举报