精华内容
下载资源
问答
  • 主要介绍了vue点击页面空白处实现保存功能,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 一开始的时候我是想着使用vuex结合vue router的beforeEach导航守卫来实现。代码如下: 首先在vuex中新增一个状态值—introduceState const store = new Vuex.Store({ strict: true, // process.env.NODE_ENV !
  • 主要介绍了vue页面实现当前页面刷新或跳转时提示保存,在当前页面刷新或跳转时提示保存并可取消刷新,以防止填写的表单内容丢失,感兴趣的小伙伴们可以参考一下
  • 最近做一个表单页面,所有的交互效果都是到最后表单保存提交才实现的数据交互,因此出现用户可能不保存页面,而离开此页面,造成数据损失,为了避免这样的情况,特意做一个弹窗提示功能,用watch监听数据,如果数据...

    最近做一个表单页面,所有的交互效果都是到最后表单保存提交才实现的数据交互,因此出现用户可能不保存页面,而离开此页面,造成数据损失,为了避免这样的情况,特意做一个弹窗提示功能,用watch监听数据,如果数据发生变化,用户点击了其他地方链接要离开页面,则根据beforeRouteLeave离开该页面时出发的卫士,从而出现弹窗提示,让用户选择是否离开次页面,如果watch监听数据没发生变化,则不必提示。
    在这里插入图片描述
    监听代码如下:

     watch: {
        datas: {
          handler (val) {
            if (val) {
              this.count++
            }
          },
          deep: true
        }
      },
    

    判断数据变化的次数,因为刚加载数据未完全加载的时候,datas是空对象,待加载完之后,则出现一次数据变化, deep主要是深层次监听,因为数据是层层对象,比较复杂
    判断要离开的代码是:

    beforeRouteLeave (to, from, next) {
    // 判断数据是否修改,如果修改按这个执行,没修改,则直接执行离开此页面
        if (this.count > 1) {
          if (this.status) {
            next()
            return
          }
          // 弹窗显示
          this.$refs.leaveTip.changeLimitDialog(true)
          this.leave = to
          next(false)
        } else {
          next()
        }
      },
    

    弹窗触发的事件方法如下:

     leavelHandler (b) {
          const { leave } = this
          if (b) {
          // 主要判断是否触发弹窗事件了,
            this.status = true
            this.$router.push({ name: leave.name, query: leave.query, params: leave.params })
          } else {
            this.status = false
          }
          this.$refs.leaveTip.changeLimitDialog(false)
        }
    

    整体代码如下:

    <template>
      <div class="collect-box">
        <crumb-tit>
          <span slot="breadTit">提交信息配置</span>
          <span slot="secondTit">提交信息配置</span>
        </crumb-tit>
        <main-i />
        <leave-tip-dialog
          ref="leaveTip"
          @leavelHandler="leavelHandler"
        >
          <div slot="tip-slot">
            有部分配置变更尚未保存,<br>
            确定要离开当前页面妈
          </div>
        </leave-tip-dialog>
      </div>
    </template>
    <script>
    import CrumbTit from '@/components/pc/config/CrumbTit'
    import MainI from '@/components/pc/config/collect/MainLayout'
    import LeaveTipDialog from '@/components/pc/LeaveTipDialog'
    import { mapState } from 'vuex'
    export default {
      components: {
        MainI,
        CrumbTit,
        LeaveTipDialog
      },
      data () {
        return {
          leave: {},
          status: false,
          count: 0
        }
      },
      computed: {
        ...mapState('config/collect', ['datas', 'datasReady'])
      },
      watch: {
        datas: {
          handler (val) {
            if (val) {
              this.count++
            }
          },
          deep: true
        }
      },
      beforeRouteLeave (to, from, next) {
        if (this.count > 1) {
          if (this.status) {
            next()
            return
          }
          this.$refs.leaveTip.changeLimitDialog(true)
          this.leave = to
          next(false)
        } else {
          next()
        }
      },
      mounted () {
      },
      methods: {
        leavelHandler (b) {
          const { leave } = this
          if (b) {
            this.status = true
            this.$router.push({ name: leave.name, query: leave.query, params: leave.params })
          } else {
            this.status = false
          }
          this.$refs.leaveTip.changeLimitDialog(false)
        }
      }
    }
    </script>
    
    

    弹窗LeaveTipDialog:

    <template>
      <a-modal
        :visible.sync="TipDialogVisible"
        width="400px"
        class="member-limit-dialog-box "
        :footer="null"
        @cancel="TipDialogVisible=false"
      >
        <div
          class="dialog-tip-box"
        >
          <i class="icon iconfont iconicon-test68" />
          <h2>注意</h2>
          <div class="d-tip-con">
            <slot name="tip-slot" />
          </div>
          <div class="limit-btn-box">
            <a-button
              type="primary"
              @click="leavelHandler(false)"
            >
              留在页面
            </a-button>
            <a-button
              class="ml-16"
              @click="leavelHandler(true)"
            >
              离开页面
            </a-button>
          </div>
        </div>
      </a-modal>
    </template>
    <script>
    export default {
      data () {
        return {
          TipDialogVisible: false
        }
      },
      computed: {
        cId () {
          return this.orgItemData.cid
        }
      },
      methods: {
        changeLimitDialog (b) {
          this.TipDialogVisible = b
        },
        leavelHandler (b) {
          this.$emit('leavelHandler', b)
        }
      }
    }
    </script>
    
    
    展开全文
  • 页面存在编辑框,当用户进入编辑状态时,如果没有点击保存就离开页面,需弹窗提示。如: 实现原理: 使用路由守卫beforeRouteLeave进行控制,当路由守卫监听到页面路由发生改变时触发弹窗。 实现代码: mounted() ...

    需求分析:

    页面存在编辑框,当用户进入编辑状态时,如果没有点击保存就离开页面,需弹窗提示。如:
    在这里插入图片描述

    实现原理:

    使用路由守卫beforeRouteLeave进行控制,当路由守卫监听到页面路由发生改变时触发弹窗。

    实现代码:

    	mounted() {
    		......
    	}
    
      // 使用路由守卫判断是否离开当前页面
      beforeRouteLeave(to, form, next) {
        if (this.editingRowId !== '') { // 此处为个人项目条件判断,当条件成立时才执行路由守卫
          this.$confirm('当前信息未保存,离开页面将会放弃所有修改数据,', '提示', {
            closeOnClickModal: false,
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
          	// 点击确定则往下执行
            next()
          }).catch(() => {
    		// 取消则关闭弹窗不执行
    	  })
        } else {
          // 条件不成立则继续往下执行
          next()
        }
      },
    
    	methods: {
    		......
    	}
    
    展开全文
  • 主要介绍了使用vue实现HTML页面生成图片的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • vue实现学生页面

    千次阅读 2020-05-31 14:32:23
    1.在App.vue中监听login的状态,当login从false变为true,表示用户已经登录。 watch:{ login(val){//监听login的状态变化 if(val){ this.loadDetails(); } } }, methods:{ loadDetails(){//请求学生信息...

    1.在App.vue中监听login的状态,当login从false变为true,表示用户已经登录。

     watch:{
        login(val){//监听login的状态变化
          if(val){
            this.loadDetails();
          }
        }
      },
      methods:{
        loadDetails(){//请求学生信息的接口,测试一下
            alert("你好,小明同学");
        }
      }

    2.请求接口测试

    import {api} from "./utils/api"
    methods:{
        loadDetails(){
            //请求地址,参数
            api.get("/student/detail",{headers:{Token:this.info.token}}).then(data=>{
              console.log(data);
            })
        }
      }

    3.请求回来的数据怎么保存呢?

    通过data来定义数据,初始化数据

    data(){
        return{
          student:{
            orgs:[],//组织
            stats:{},//状态
            assignments:[]//所有作业的信息
          }
        }
      }

    4.请求接口成功后,给这些初始化的参数赋值,把请求到的数据保存到data里面

     methods:{
        loadDetails(){
            api.get("/student/detail",{headers:{Token:this.info.token}}).then(data=>{
              console.log(data);
              this.student.orgs=data.orgs;
              this.student.assignments=data.assignments;
              this.student.stats=data.stats;
            })
        }
      }

    5.因为有自动登录这个功能,刷新的时候login的状态不会改变,请求的函数不会被执行,怎么解决?

    所以我们要使用created钩子函数,每次刷新都会加载,先判断是否登录

     created(){
       if(this.login){
         this.loadDetails();
       }
      }

    6.判断头部信息放老师信息还是学生信息,isTeacher属性我们通过computed监听了

     <h2>HappyStudy</h2>
            <div>
              <div v-if="isTeacher">我是老师头部信息</div>
              <div v-else>我是学生头部信息</div>
            </div>

    7.渲染数据到页面上

    <div v-else>
                <h4>
                  <span>{{info.full_name}}</span>
                  <span>学号:{{info.name}}</span>
                </h4>
                <h5>
                  <span v-for="(org,index) in student.orgs" :key="`${org}_${index}`">{{org}}</span>
                </h5>
                <div>
                 <span>{{student.stats.uncommitted}}个作业待提交</span>
                 <span>{{student.stats.revising}}个作业待批改</span>
                 <span>{{student.stats.improvable}}个作业需完善</span>
                 <span>{{student.stats.finished}}个作业已完成</span>
                </div>
                <a href="javascript:;">
                  <a-button icon="home">代码仓库</a-button>
                </a>
                <a-button icon="logout">退出</a-button>
              </div>

    8.样式不好看,内容被挤到下面去了,所以我们给父级设置Flex布局,等等

    为了使退出按钮能够居中

    .out-center{
      align-self: center;
    }

    全部

    <style lang="scss">
    #App{
     min-height: 100vh;
    }
    .header{
      h2,h4,h5{
        color: white;
      }
      .right>.flexrow>*{
       margin-right: 25px;
      }
      .label{
        color: white;
        padding: 0 5px;
      }
    }
    .flexrow{
      display: flex;
      flex-direction: row;//行
      justify-content: space-between;
      flex-wrap: nowrap;
    }
    .right{
      width: auto;
      flex-grow: 1;
      display: flex;
      flex-direction: row;//行
      justify-content: space-between;
      flex-wrap: nowrap;
    }
    .flexcol{
      display: flex;
      flex-direction:column;//行
      flex-wrap: nowrap;
      justify-content: space-evenly;//间隔一样
      span{
        flex: 1;
        max-height: 20px;
        line-height: 20px;
      }
    }
    .out-center{
      align-self: center;
    }
    .btn-space{
      margin: 0 0 0 15px;
    }
    </style>

    样式方面,仁者见仁,智者见智,这边就不多说了

    9.代码仓库就不放链接了,退出按钮的功能已经做了,在user.js中已经实现了,那么我要怎么去触发函数呢?

    不需要自己再去写,通过 $store.dispatch去触发

    <a-button icon="logout" class="btn-space out-center" @click="$store.dispatch('user/logout')">退出</a-button>

    10.后台管理系统,脱离不了表格的使用,表格的使用虽然复杂,但是我们可以从基本用法开始用起

    我们需要把后台传过来的数据放在表格里面

    11.父组件往子组件里面传值,通过props

    11.1.绑定上自定义的属性

     <Student v-else :student="student"></Student>

    11.2.接收,然后渲染

    export default {
        props:["student"]
    }

    12.表格里面传的是数组的数据

    最基本的使用要绑定上两个,一个是data-source(数据数组),一个是columns(表格列的配置)

    dataIndex:'name',我们应该去渲染数据里面name的字段

    13.官网上有定义data,数据是展示给我们看的,而我们不需要去定义,因为我们数据是从后台传过来的,我们需要去定义columns

    <a-table :columns="columns" :data-source="data"></a-table>

    14.已渲染出一列数据,如下,其他以此类推

    <template>
        <div>
            <a-table :columns="columns" :dataSource="student.assignments"></a-table>
        </div>
    </template>
    <script>
    export default {
        data(){
           return{
               columns:[{
                   title:"课程",
                   dataIndex:"org_name" //dataIndex要渲染哪个字段
               }]
           }
        },
        props:["student"]
    }
    </script>
    <style lang="scss">
    
    </style>

    15.使用dataIndex是直接渲染,但是有的数据需要拼接或者运算,怎么办呢?

    使用customRender,生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并

     data(){
           return{
               columns:[
               {
                   title:"课程",
                   dataIndex:"org_name"
               },
                {
                   title:"作业名称",
                   dataIndex:"name"
               },
                {
                   title:"开始-截止时间",
                   //这行的值,数据,索引
                   customRender(text,record,index){
                       console.log(record);
                     return `${record.start_time}~${record.end_time}`
                   }
               }
               
               ]
           }
        }

    16.怎么渲染出按钮呢?

    通过scopedSlots,使用 columns 时,可以通过该属性配置支持 slot-scope 的属性,如 scopedSlots: { customRender: 'XXX'}

    16.1.先在columns里面定义scopedSlots

    data(){
           return{
               columns:[
               {
                   title:"课程",
                   dataIndex:"org_name"
               },
                {
                   title:"作业名称",
                   dataIndex:"name"
               },
                {
                   title:"开始-截止时间",
                   //这行的值,数据,索引
                   customRender(text,record,index){
                       console.log(record);
                       console.log(text);
                       console.log(index);
                     return `${record.start_time}~${record.end_time}`
                   }
               },
               {
                   title:"操作",
                   //渲染按钮
                   scopedSlots:{
                       customRender:"operation" //对应slot里面的名称
                   }
               } 
               ]
           }
        }

    16.2.然后在slot标签里面编写按钮

    <template>
        <div>
            <a-table :columns="columns" :dataSource="student.assignments">
                <template slot="operation">
                      <a-upload name="file">
                          <a-button icon="up">上传</a-button>
                      </a-upload>
                </template>
            </a-table>
        </div>
    </template>

    17.上传是通过id来上传,不需要使用axios

    <script>
    const HOST="http://sandbox_api.estudy.xyz"
    export default {
        data(){
           return{
               uploadHost:HOST+"/student/upload",//上传地址
           }
        },
    }
    </script>

     然后在action中绑定上请求地址

    <template>
        <div>
            <a-table :columns="columns" :dataSource="student.assignments">
                <template slot="operation">
                      <a-upload name="file" :action="uploadHost">
                          <a-button icon="up">上传</a-button>
                      </a-upload>
                </template>
            </a-table>
        </div>
    </template>

    18.上传的时候,不仅要传id,也要传token

    组件库里面的headers:设置上传的请求头部

    18.1.首先要先获取info的信息,通过

    import {mapState} from "vuex"; //引入
    export default {
        computed:{
          ...mapState("user",["info"])
        }
    }

    18.2.在headers请求头里面传参:把token对象传进去

    <template slot="operation">
                      <a-upload name="file" :action="uploadHost" :headers="{Token:info.token}">
                          <a-button icon="up">上传</a-button>
                      </a-upload>
                </template>

    19. slot-scope里面可以传三个参数,text,record,index,

    我们从record中取出上传文件的id,把id也传过去

     <template slot="operation" slot-scope="record">
                      <a-upload 
                      name="file" 
                      :action="uploadHost" 
                      :headers="{Token:info.token}"
                      :data="{id:record.assignment_id}">
                          <a-button icon="upload">上传</a-button>
                      </a-upload>
                </template>

     20.我们上传文件成功或者失败要给个提示什么的,要加上回调函数

    20.1.绑定上点击事件

     <template slot="operation" slot-scope="record">
                      <a-upload 
                      name="file" 
                      :action="uploadHost" 
                      :headers="{Token:info.token}"
                      :data="{id:record.assignment_id}"
                      @change="changeUpload">
                          <a-button icon="upload">上传</a-button>
                      </a-upload>
                </template>
    methods:{
            changeUpload(info){
                console.log(info);
            }
        },

    看一下是什么信息,再来判断

    20.2.根据后台数据,判断是上传成功或者上传失败

    methods:{
            changeUpload(info){
                console.log(info);
                if(info.file.status==="done"&&info.file.response.data){
                    this.$message.info("上传成功");
                }else if(info.file.status==="error"){
                    this.$notification.error({
                        message:"上传失败",
                        description:info.file.response.errorMessage
                    })
                }
            }
    }

    21.不想要上传时有进度条,怎么去掉?

     :showUploadList="false" ,可以传对象或者布尔

    <template slot="operation" slot-scope="record">
                      <a-upload 
                      name="file" 
                      :action="uploadHost" 
                      :headers="{Token:info.token}"
                      :data="{id:record.assignment_id}"
                      @change="changeUpload"
                      :showUploadList="false">
                          <a-button icon="upload">上传</a-button>
                      </a-upload>
                </template>

     以上,我们完成上传功能。

    接下来,实现下载功能

    22.只有作业已经上传过了,才有下载按钮,否则不出现下载按钮

    根据后台有没有work这个字段,来判断下载按钮有没有

    <template>
        <div>
            <a-table :columns="columns" :dataSource="student.assignments">
                <template slot="operation" slot-scope="record">
                      <a-upload 
                      name="file" 
                      :action="uploadHost" 
                      :headers="{Token:info.token}"
                      :data="{id:record.assignment_id}"
                      @change="changeUpload"
                      :showUploadList="false">
                          <a-button icon="upload">上传</a-button>
                      </a-upload>
                      <a v-if="record.work" href="">
                           <a-button icon="download">下载</a-button>
                      </a>
                </template>
            </a-table>
        </div>
    </template>

    23.下载请求的地址:在data中定义

    downloadHost:HOST+"/student/download"

    24.下载的时候,我们去绑定href,要带上下载的id地址和类型(因为是学生页面)

    <a v-if="record.work" :href="`${downloadHost}?id=${record.work.id}&type=student`">
                           <a-button icon="download">下载</a-button>
    </a>

    25.状态也是根据有没有work这个字段来显示的

    {
                   title:"状态",
                   customRender(text,record){
                       console.log(record.work);
                       console.log(text);
                   }
               }

    25.1. 因为后台传给我们的是数字,所以我们要映射成对象

    import {mapState} from "vuex";
    const work_status={
        "0":"待批改",
        "1":"需完善",
        "2":"已完成"
    }

    25.2. 如果有work的话,我们就传入映射的对象,如果没有的话,就是直接显示未提交

    {
                   title:"状态",
                   customRender(text,record){
                       console.log(record.work);
                       console.log(text);
                       return record.work ? work_status[record.work.status] : "未提交"
                   }
               }

    26.信息功能

    26.1.columns里面去编写

    {
                   title:"信息",
                   //渲染info的slot
                   scopedSlots:{
                       customRender:"info"
                   }
               }

     26.2.渲染出数据

    <!-- 行数据record -->
                <template slot="info" slot-scope="record">
                     <div v-if="record.work">
                        <div v-if="record.work.status==0">
                               <!-- 如果老师没批改作业,显示学生提交作业的时间 -->
                               {{record.work.teacher_download_time.slice(0,10) ==="0000-00-00" ?
                              record.work.commit_time : record.work.teacher_download_time }}         
                        </div>
                     </div>
                </template>

    26.3.完善一下,添加一些提示信息

     <!-- 行数据record -->
                <template slot="info" slot-scope="record">
                     <div v-if="record.work">
                        <div v-if="record.work.status==0">
                               <!-- 如果老师没批改作业,显示学生提交作业的时间 -->
                               {{record.work.teacher_download_time.slice(0,10) ==="0000-00-00" ?
                              `${record.work.commit_time}提交` : `${record.work.teacher_download_time}老师已经下载` }}         
                        </div>
                     </div>
                </template>

    26.4.加上其他的状态

     <template slot="info" slot-scope="record">
                     <div v-if="record.work">
                        <div v-if="record.work.status==0">
                               <!-- 如果老师没批改作业,显示学生提交作业的时间 -->
                               {{record.work.teacher_download_time.slice(0,10) ==="0000-00-00" ?
                              `${record.work.commit_time}提交` : `${record.work.teacher_download_time}老师已经下载` }}         
                        </div>
                         <div v-else-if="record.work.status==1">
                               <p>{{`${record.work.review_time}老师提交修改意见`}}</p>    
                               <a-button>查看详情</a-button>
                        </div>
                        <div v-else>
                               <p>{{`${record.work.review_time}老师完成批改`}}</p>    
                               <a-button>查看详情</a-button>
                        </div>
                     </div>
                </template>

    27.查看详情功能,需要用到模态框

    27.1. 首先我们要在data里面定义visible为false

     <!-- 行数据record -->
                <template slot="info" slot-scope="record">
                     <div v-if="record.work">
                        <div v-if="record.work.status==0">
                               <!-- 如果老师没批改作业,显示学生提交作业的时间 -->
                               {{record.work.teacher_download_time.slice(0,10) ==="0000-00-00" ?
                              `${record.work.commit_time}提交` : `${record.work.teacher_download_time}老师已经下载` }}         
                        </div>
                         <div v-else-if="record.work.status==1">
                               <p>{{`${record.work.review_time}老师提交修改意见`}}</p>    
                               <a-button @click="visible=true">查看详情</a-button>
                        </div>
                        <div v-else>
                               <p>{{`${record.work.review_time}老师完成批改`}}</p>    
                               <a-button @click="visible=true">查看详情</a-button>
                        </div>
                     </div>
                </template>
     <a-modal :visible="visible" @cancel="visible=false">
                <h4>批改意见</h4>
                <p></p>
            </a-modal>

     27.2.我们需要teacher_review这个字段,但是这个字段在record.work中

    这边偷懒,但是会报错,因为模态框想要boolean类型,我们却把对象传了过去,所以要强制类型转换

     <template slot="info" slot-scope="record">
                     <div v-if="record.work">
                        <div v-if="record.work.status==0">
                               <!-- 如果老师没批改作业,显示学生提交作业的时间 -->
                               {{record.work.teacher_download_time.slice(0,10) ==="0000-00-00" ?
                              `${record.work.commit_time}提交` : `${record.work.teacher_download_time}老师已经下载` }}         
                        </div>
                         <div v-else-if="record.work.status==1">
                               <p>{{`${record.work.review_time}老师提交修改意见`}}</p>    
                               <a-button @click="visible=record.work">查看详情</a-button>
                        </div>
                        <div v-else>
                               <p>{{`${record.work.review_time}老师完成批改`}}</p>    
                               <a-button @click="visible=record.work">查看详情</a-button>
                        </div>
                     </div>
                </template>
     <a-modal :visible="Boolean(visible)" @cancel="visible=false">
                <h4>批改意见</h4>
                <p v-if="visible && visible.teacher_review">{{visible.teacher_review}}</p>
            </a-modal>

    27.3. 要完善一下附件的功能

    <a-modal :visible="Boolean(visible)" @cancel="visible=false">
                <h4>批改意见</h4>
                <p v-if="visible && visible.teacher_review">{{visible.teacher_review}}</p>
                <p v-if="visible && visible.teacher_upload_name">
                    <!-- 下载地址接上id和类型为老师 -->
                   <a :href="`${downloadHost}?id=${visible.id}&type=teacher`">
                       <a-button>附件</a-button>
                   </a>
                </p>
            </a-modal>

    28.我们注意到控制台有报错

    提示我们要给表格绑定上key值

    <a-table :rowKey="assignments=>assignments.assignments_id" :columns="columns" :dataSource="student.assignments">
    </a-table>

    29.antDesign里面是自动分页的,如果不需要分页的话,:pagination=false,即可

    展开全文
  • 使用vue实现HTML页面生成图片

    千次阅读 2020-03-26 15:27:15
    这篇文章写得是实现HTML页面生成图片(附带二维码)并保存,之前做过这个需求,不过当时不太会使用VUE,采用的方法是后端来生成,前端也是使用了html2canvas辅助生成,比较麻烦,并且有延迟效果,刚好看到这篇文章,...

    这篇文章写得是实现HTML页面生成图片(附带二维码)并保存,之前做过这个需求,不过当时不太会使用VUE,采用的方法是后端来生成,前端也是使用了html2canvas辅助生成,比较麻烦,并且有延迟效果,刚好看到这篇文章,转载一番,做个记录。

    背景

    随着网络的发展,越来越多的网络平台应运而生。如何获得更多的流量,吸引更多的眼球已经成为网络平台生存、发展的必要条件。现在网络平台最常见的一种宣传方式就是人邀人。
    我最近就接到一个需求,做一个海报页面,并且能保存到手机,方便用户分享给朋友,希望能够达到人邀人的效果。
    在这里插入图片描述
    给人第一感觉这个需求就是保存图片的功能,当时梳理是却发现不是那么简单:

    • 动态生成一张带logo的二维码
    • 整个海报的html部分转化成图片
    • 保存图片至手机相册

    生成带logo的二维码

    vue_qrcodes生成带logo的二维码

    安装:

    npm install vue_qrcodes -- save
    

    使用:

    <!--部分html代码-->
    <qrcode :url="qrcodeUrl"
            :iconurl="iconurl"
            :wid="298"
            :hei="278"
            :imgwid="100"
            :imghei="100">
    </qrcode>
    
    // 部分js代码
    import qrcode from 'vue_qrcodes'
    //...省略其他代码
    components: {
        qrcode
     }
    
    

    问题来了:二维码出现了,但是二维码和logo大小并不是你想要,无法自适应。那就需要我们重置二维码和logo的样式。

    .logoimg {
          height: 100px !important;
          width: 100px !important;
          margin-top: -50px !important;
          margin-left: -50px !important;
        }
    #qrcode {
          margin-top: 20px;
          img {
            height: 278px !important;
            width: 298px !important;
          }
        }
    
    

    html转化为base64图片

    html转化为canvas中我选用组件 html2canvas

    yarn add html2canvas
    
    import html2canvas from 'html2canvas'
    

    为了防止页面有闪屏我用了两个div,一个存放原来的dom,一个存放canvas的生成的图片,再v-if控制展示的元素。
    在这里插入图片描述
    js调用函数:

    htmlToCanvas() {
      html2canvas(this.$refs.bill, {})
      .then((canvas) => {
        let imageUrl = canvas.toDataURL('image/png'); // 将canvas转成base64图片格式
        this.canvasImageUrl = imageUrl;
        this.isDom = false;
      });
    }
    // 二维码地址
    this.qrcodeUrl = data.data.inviteCodeAddress
    // 调用html转化canvas函数
    this.htmlToCanvas(); 
    
    

    结果如图:
    在这里插入图片描述
    除二维码其他部分已经转化为图片,二维码不显示,原因有两种可能:

    • 转化时二维码还没有加载完成
    • 转化二维码的过程中报错了

    准备采用如下方法解决:
    1.首先尝试了nextTick
    使用 nextTick 将回调延迟到下次DOM更新循环之后执行

    // 二维码地址
    this.qrcodeUrl = data.data.inviteCodeAddress 
    this.$nextTick(() => {
        // 跳用html转化canvas函数
        this.htmlToCanvas(); 
     })
    

    在这里插入图片描述
    发现二维码出来了,但是二维码的大小不对,并且控制台还是存在报错。虽然问题没有完全解决,但是二维码出现了。可以证明二维码不展示的原因是,转化时二维码没有加载完成。
    2.再尝试使用setTimeout
    使用 setTimeout 将回调延迟到指定时间之后执行

    // 二维码地址
    this.qrcodeUrl = data.data.inviteCodeAddress 
    setTimeout(()=>{
        // 调用html转化canvas函数
        this.htmlToCanvas(); 
    }, 200)
    
    

    在这里插入图片描述
    页面正常,控制台没有报错,可是logo没有展示出来。

    logo地址是:

    iconurl: 'https://XXXXX/assets/project/tosimple-pic/LOGO_1576564983633.png',
    

    项目在本地启动,可能存在跨域问题。

    htmlToCanvas() {
          html2canvas(this.$refs.bill, {
            useCORS: true // 解决图片跨域问题
          }).then((canvas) => {
            // 将canvas转成base64图片格式
            let imageUrl = canvas.toDataURL('image/png'); 
            this.canvasImageUrl = imageUrl;
            this.isDom = false;
          }).catch((e) => console.log(e));
        }
    
    

    至此html成功转化为图片。

    图片保存至手机

    采用的是微信长按保存图片,提示用户长按图片可以保存即可。

    展开全文
  • 引入插件 npm install qrcodejs2 --save npm install --save html2canvas 在需要的组件里引用 import html2canvas from 'html2canvas' import QRCode from 'qrcodejs2' 上代码 推荐好友领福利 长按保存二维码可分享 ...
  • 下载插件: ... 引用: ...//屏幕截图、保存图片到相册 handleExport() { let htmlDom = document.getElementById("long"); // 你要截图的元素 可直接是img var FileSaver = require("file-saver"); th
  • 使用Vue实现图片上传的三种方式

    万次阅读 多人点赞 2019-03-06 19:26:48
    项目中需要上传图片可谓是经常遇到的需求,本文将介绍 3 种不同的图片上传方式,在这总结分享一下,有什么建议或者意见,请...我们就以Vue、Element-ui,封装组件为例子聊聊如何实现这个功能。其他框架或者不用框架...
  • 主要介绍了vue实现表单未编辑或未保存离开弹窗提示功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • 保存页面的数据,页面显示就执行某个函数,页面隐藏就执行某个函数实现方式: 1.在路由内设置页面是否需要缓存; 示例代码:(在需要的组件里面添加meta 对象,keepAlive属性,keepAlive的值为是否需要缓存组件) ...
  • Vue实现页面导航实战

    千次阅读 2020-08-22 15:24:32
    4使用views页面级组件,使用router设置页面 二创建项目 1创建项目 F:\vue\proj>vue create proj 2选择必要组件 ? Check the features needed for your project: (*) Babel ( ) TypeScript ( ) Progressive...
  • 需求:将整个页面转化为图片,或者将部分转化为图片 解决方案: 1.引入html2canvas npm install --save html2canvas或者:yarn add html2canvas 2.将html2canvas 引入到组件中 ,vant 的组件 ImagePreview 引入 ...
  • vue自动保存表单功能的实现

    千次阅读 2018-10-03 14:13:00
    最近想实现一个表单内容的自动保存,原来是想通过监听表单的change事件来解决.但后面想想,现在都是数据驱动了,监听数据变化就行了. 页面表单如下: <el-form label-width="100px" :model="modalFormData" ref=...
  • vue实现刷新页面仍保持选中状态

    千次阅读 2019-06-06 18:51:58
    参考:https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html
  • vue实现移动端H5页面截图 1、vue使用html2canvas实现移动端H5页面截图并下载。 2、html2canvas能够实现在用户浏览器端直接对整个或部分页面进行截屏。这个html2canvas脚本将当页面渲染成一个Canvas图片,通过读取DOM...
  • 2、vue配置 main.js importhtml2canvasfrom'html2canvas' Vue.prototype.$html2canvas=html2canvas 3、iframe <iframeref="iframe"src='.。。/index.html'></iframe> 4、组件vue代码 download_if...
  • this1.downImg=dataURL;...但是实现功能一样得。 但是注意不能使用网络图片。否则别的图片就加载不出来。可以使用canvas绘图 查看这里https://blog.csdn.net/qq_33769914/article/details/53911240
  • 主要介绍了vue项目实现表单登录页保存账号和密码到cookie功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
  • vue 页面保存成pdf

    2019-06-04 16:09:32
    安装插件 jspdf html2canvas npm install -S jspdf npm install -S ... 使用 (简单粗暴直接上) ...// 导出页面为PDF格式 import html2Canvas from 'html2canvas' import JsPDF from 'jspdf' export ...
  • vue前端实现点击按钮将页面svg内容保存到本地 使用插件saveSvgAsPng 详细官方文档:http://npm.taobao.org/package/save-svg-as-png 首先下载安装依赖包:npm install save-svg-as-png //引入包 import ...
  • 1、使用keep-alive:include="caches"来实现页面状态的保留,通过动态修改caches来达到局部页面缓存,include会缓存包含的页面。所以你可以将需要缓存的几个页面放在caches中,当退出这几个页面的时候再取消缓存。 2...
  • 今天小编就为大家分享一篇Vue保存数据到磁盘文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 本文主要讲解用vue实现三个页面之间的跳转以及登录状态的实现,css还在努力学习中,所以界面做的很丑lol 要求: 1.三个页面,登录页面Login,注册页面Register,主页Home 2.用route路由实现不同页面逻辑跳转 3....
  • 主要介绍了vue实现路由不变的情况下,刷新页面操作,结合实例形式分析了vue路由不变的情况下刷新页面具体原理、操作方法与相关注意事项,需要的朋友可以参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,524
精华内容 11,809
关键字:

vue怎么实现保存页面

vue 订阅