项目七遇到的知识点

一、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 | { [key: string]: string | Symbol | Object }
  • 这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
(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

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

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

  • 效果图
    1201653-20190516113443260-1657079945.png

  • 子组件

      <template>
          <!-- 新增/修改 -->
            <div class="role-change table-mask">
              <div class="role-body">
                <div class="role-main">
                  <span
                    class="svg-container table-close"
                    @click="cancel"
                  >
                    <svg-icon icon-class="close" />
                  </span>
                  <div class="main-box">
                    <div class="main-item">
                      <p><span class="m-start">*</span>角色编码:</p>
                      <el-input v-model.trim="Code" />
                    </div>
                    <div class="main-item">
                      <p><span class="m-start">*</span>角色名称:</p>
                      <el-input v-model.trim="Name" />
                    </div>
                  </div>
                  <div class="box-btn-bg add-bg tac">
                    <el-button
                      class="f18 box-btn"
                      @click="cancel"
                    >取消</el-button>
                    <el-button
                      class="f18 box-btn"
                      @click="addSubmit"
                    >保存</el-button>
                  </div>
                </div>
              </div>
            </div>
          </template>
          <script lang="ts">
            import { Watch, Component, Vue, Emit, Prop } from "vue-class-decorator";
            import { addRole, getRoleDetails, getUpdateRole } from "@/api/System/role";
    
            @Component
            export default class AddRole extends Vue {
              Code = ""; // 角色编码
              Name = ""; // 角色名称
              @Emit("addRole")
              addRole(flag) {}
              @Prop({ type: String, default: null })
              addId: string;
              cancel() {
                this.addRole(false);
              }
              addSubmit() {
                if (this.Code === "") {
                  this.$message({
                    message: "请输入角色编码",
                    type: "warning"
                  });
                } else if (this.Name === "") {
                  this.$message({
                    message: "请输入角色名称",
                    type: "warning"
                  });
                } else {
                  if (this.addId) {
                    // 修改接口
                      // 调用自定义方法
                      this.addRole(true);
                  } else {
                    // 新增接口
                   this.addRole(true);
                  }
                }
              }
            }
          </script>
  • 父组件

      <!-- 新增/修改 -->
      <add-role
      v-if="roleShow"
      :addId="addId"
      @addRole="addRole"
      ></add-role>
      <script lang="ts">
          import AddRole from "./components/AddRole.vue";
          @Component({
              components: {
                AddRole
              }
           })
           export default class RoleList extends Vue {
              roleShow = false; // 默认弹框不显示
              addId = null; // 传给子组件的id
              // 新增/修改的自定义方法
              addRole(flag) {
                if (flag) {
                }
                this.addId = null;
                this.roleShow = false;
              }
              // 点击新增按钮
              add(){
                  this.roleShow = true;
              }
              //点击修改按钮
              edit(){
                  this.addId = 'newId';
                  this.roleShow = true;
              }
           }
      </script>
  • 思路
  • 父子之间传值,点击修改的时候传newId,新增的时候不传默认是null,这样就可以在子组件里区分是新增页面还是修改页面

三、Element 默认勾选表格 toggleRowSelection

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

  • 效果图
    1201653-20190516113501488-64144313.png

1、子组件内容

(1)、html
<template>
  <div class="table-mask">
    <div class="table-main">
      <el-table
        ref="multipleTable"
        :data="tableData"
        style="width: 100%"
        border
        row-key="id"
        @selection-change="handleSelectionChange"
        @row-click="clickRow"
      >
        <el-table-column
          type="selection"
          width="50"
          :reserve-selection="true"
          align="center"
        >
        </el-table-column>
        <el-table-column
          label="日期"
          width="100"
          align="center"
        >
          <template slot-scope="scope">{{ scope.row.date }}</template>
        </el-table-column>
        <el-table-column
          prop="name"
          label="姓名"
          width="90"
          align="center"
        >
        </el-table-column>
        <el-table-column
          prop="address"
          align="center"
          label="地址"
        >
        </el-table-column>
      </el-table>
      <div>
        <el-button
          type="info"
          @click.stop="cancel"
        >取消</el-button>
        <el-button
          type="primary"
          @click.stop="submit"
        >保存</el-button>
      </div>
    </div>
  </div>
</template>
(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"
>点击弹出表格</el-button>
<my-table
  v-if="isTableShow"
  :hasArray="hasArray"
  @ChangeClick="ChangeClick"
></my-table>
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、知识点

  • 官网
    1201653-20190516113528435-1799985269.png
(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"
>
</el-tree>
<!-- default-checked-keys   默认勾选的节点的 key 的数组 -->
  • 方法

      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);
  
  • 打印效果
    1201653-20190516131333440-1979834755.png

vue store存储commit和dispatch

  • this.$store.commit("toShowLoginDialog",true)
  • this.$store.dispatch('toShowLoginDialog',false)
  • 主要区别是
  • dispatch:含有异步操作,例如向后台提交数据,写法:this.$store.dispatch('mutations方法名',值)
  • commit:同步操作,写法:this.$store.commit('mutataions方法名',值)

转载于:https://www.cnblogs.com/DCL1314/p/10874650.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值