Electron + Vue跨平台应用(七)基础技法(一)

445 阅读8分钟

Electron + Vue + Vscode构建跨平台应用(一)知识点补充
Electron + Vue + Vscode构建跨平台应用(二)Electron + Vue环境搭建
Electron + Vue + Vscode构建跨平台应用(三)利用webpack搭建vue项目
Electron + Vue + Vscode构建跨平台应用(四)利用Electron-Vue构建Vue应用详解
Electron + Vue + Vscode构建跨平台应用(五)Electron-Vue项目源码分析
Electron + Vue跨平台应用(六)效果还不错的登录页面

  在开发跨端应用的时候,总是会遇到各种问题或者思考一些问题,所以用文章记载一下,算是知识库吧,目录如下 点击下面的链接即可跳转到对应内容

1. 为什么要使用计算属性,它和方法有什么区别
2. 如何关闭eslint代码检查
3. 元素如何根据不同的类名设置不同的css样式
4. ref,refs和this.el
5. 简单理解vue生命周期
6. 语法糖
7. NPM install -save 和 -save-dev的区别
8. 自定义Dialog,并在父组件中与其交互
9. ES6中的箭头函数
10. 如何在Vue中定义全局变量,全局函数


1. 为什么要使用计算属性,它和方法有什么区别

  计算属性依赖于数据对象进行缓存的,当依赖的数据对象没有变化的时候,再次调用计算属性不会执行里面的逻辑,而是直接返回;而方法每调用一次,他就重新执行一次;

<!DOCTYPE html>
<html>

<body>
    <div id="app">{{ reversedMessage }} 第一次调用计算属性
        <div>{{ reversedMessage }} 第二次调用计算属性</div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        /* eslint-disable */
        var appVue = new Vue({
            el: '#app',
            data: {
                foo: 'this is vue learning',
                state: 'false'
            },
            computed: {
                reversedMessage: function () {
                    console.log('**计算属性中的reversedMessage**')
                    return this.foo.split('').reverse().join('')
                }
            },
        });

    </script>
    <style>
    </style>
</body>

</html>

  在示例代码里面我们有两处使用了计算属性reversedMessage,我们看一下输出

在这里插入图片描述
  从输出可以看出计算属性reversedMessage依赖数据成员foo,当foo没有发生变化的时候,这个方法只在第一次做了执行,第二次就执行返回了;

   注意点

  计算属性虽然写法上是xxxx:function(){ },有点像一个方法,但是在使用的时候你不能带上(),正如我们上面代码的第5行,如果你写成{{ reversedMessage ()}}的形式,就会报错

在这里插入图片描述

2. 如何关闭eslint代码检查

  针对单个文件可以添加如下代码即可,如第11行

/* eslint-disable */

他表示后续的代码不需要使用eslint进行代码检查

3. 元素如何根据不同的类名设置不同的css样式

  最根本的就是根据不同的类名或者id进行不同的css样式配置,即v-bind:class的使用
<!DOCTYPE html>
<html>

<body>
    <div id="app">
        <button @click="styleCss = 'newMyDiv'">change styleCss value</button>
        <div v-bind:class="styleCss">删除</div>
    </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        /* eslint-disable */
        var appVue = new Vue({
            el: '#app',
            data: {
                styleCss: 'mydiv'
            }
        });

    </script>
    <style>
        button {
            width: 200px;
            height: 20px;
            border: 1px solid #FF6699;
            margin: 20px;
            display: block;
        }

        .mydiv {
            width: 200px;
            height: 30px;
            text-align: center;
            background: #FF6699;
            cursor: pointer;
        }

        .newMyDiv {
            width: 200px;
            height: 30px;
            text-align: center;
            background: blue;
            cursor: pointer;
        }
    </style>
</body>

</html>

  第6行,修改div的类名为newMyDiv,则使用newMyDiv样式   第7行,设置div的类名为mydiv,则使用mydiv样式

  上面的写法我们还可以优化成如下

v-bind:class="{mydiv:endScan ,newMyDiv:!endScan}"

  其语法为类名:变量;如果变量为true,则给该元素绑定上对应的类名 上面的代码的含义是如果endScan为true,则类名为mydiv,如果endScan为false,则类名为newMyDiv

   注意点 因为类名是一个字符串,为了阅读起来更方便,最好写成如下形式

v-bind:class="{'mydiv':endScan ,'newMyDiv':!endScan}"

完整代码如下

<!DOCTYPE html>
<html>

<body>
    <div id="app">
        <button @click="changeAttr()">修改属性</button>
        <div v-bind:class="{'mydiv':endScan ,'newMyDiv':!endScan}">删除</div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        /* eslint-disable */
        var appVue = new Vue({
            el: '#app',
            data: {
                endScan: true
            },
            methods: {
                changeAttr() {
                    this.endScan = !this.endScan;
                }
            }
        });

    </script>
    <style>
        button {
            width: 200px;
            height: 20px;
            border: 1px solid #FF6699;
            margin: 20px;
            display: block;
        }

        .mydiv {
            width: 200px;
            height: 30px;
            text-align: center;
            background: #FF6699;
            cursor: pointer;
        }

        .newMyDiv {
            width: 200px;
            height: 30px;
            text-align: center;
            background: blue;
            cursor: pointer;
        }
    </style>
</body>

</html>

4. ref,$refs和this.$el

  ref即reference的缩写,定义为引用,简单的理解就是如果ref定义在一个元素上,则我们可以通过 $refs来获取该DOM元素,如果ref定义在一个组件上,则我们可以通过 $refs来获取该组件
<!DOCTYPE html>
<html>

<body>
    <div id="app">
        <button ref='useRef' @click="showRedUse()">使用Ref</div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        /* eslint-disable */
        var appVue = new Vue({
            el: '#app',
            methods: {
                showRedUse() {
                    console.log(this.$refs.useRef)     
                }
            }
        });

    </script>
    <style>
        button {
            width: 200px;
            height: 20px;
            border: 1px solid #FF6699;
            margin: 20px;
            display: block;
        }
    </style>
</body>

</html>

  通过输出我们可以发现

在这里插入图片描述

  其指向的就是我们的button元素,其中this.$refs表示获取该页面中所有的引用,this.$refs.useRef则表示获取名为useRed的引用   根本含义其实和JS中通过document.getElementById是一样的

而this.el则是在mounted中才会创建,其中this指向组件的实例。el指向当前组件的DOM元素

5. 简单理解vue生命周期

   生命周期的理解有注意我们更新的在相应的阶段进行逻辑设置,这和Android里面的生命周期其实是一样。                     

在这里插入图片描述
   一个VUE组件的本生命周期基应该会经历如下阶段

beforeCreate -> created -> beforeMount -> mounted -> beforeUpdate -> updated -> beforeDestroy -> destroyed

   通常创建vue实例有如下方法

//第一种方法,这种方法多在vue项目中的main.js中,用于绑定app元素,使用App模板等
new Vue({
    components: { App },
    router,
    store,
    template: '<App/>'
}).$mount('#app')
//第二种方法,这种方法多在一个单独的vue文件中,一个vue文件可以理解为一个vue实例
<template>
</template>

<script>
export default {
  name: 'login-page',
  data () {
    return {
    }
  },
  beforeCreate () {

  },
  created () {

  },
  beforeMount () {
  },

  methods: {
  }
}
</script>
<style>
</style>

//第三种方法,通过el的方式将vue实例和app元素进行绑定
    <script>
        /* eslint-disable */
        var appVue = new Vue({
            el: '#app',
            data: {
                endScan: true
            },
            methods: {
                changeAttr() {
                    this.endScan = !this.endScan;
                }
            }
        });
    </script>
  1.   当new vue组件或者引入vue模块的时候,beforeCreate,created方法会被执行,这两个方法并没有渲染出页面,但是这两个方法会和vue实例中的data属性进行绑定,同时当new vue组件或者引入vue模块的时候,beforeCreate,created方法会被执行,这两个方法并没有渲染出页面,但是这两个方法会和vue实例中的data属性进行绑定

  2.   紧接着会判断你是否使用了el元素,当没有el元素的时候,如方法一,说明你没有绑定了一个html元素,所以这时候当且仅当执行$mount('xxx')的时候,才会执行后面的生命周期;当有el元素的时候,如方法三,说明你已经绑定了一个html元素,则会判断是否使用了templata模板(templata模板即html页面拓本)关键字,当有templata模板关键字的时候,将进入渲染方法(vue对象中有一个render函数,它是以createElement作为参数,然后做渲染操作)准备渲染页面,当没有templata模板关键字的时候,则会使用当前html页面中的元素进行渲染(一般来说在一个单独的html文件中会使用el的方式去绑定一个html页面跟元素,同时这个html文件一般没有templata模板关键字,所以他会使用html文件中的元素进行渲染;但是对于一个Vue项目来说,一般通过mount的方法将vue和html页面跟元素进行绑定,每一个vue文件可以理解为一个vue实例)

  3.   当页面渲染元素准备好之后, beforeMount,mounted方法将会被执行,其中mounted方法对应于页面可见时发生

  4.   当页面展示之后,vue后台会检测数据是否发生了变化,当数据发生变化的时候, beforeUpdate方法会被执行,然后虚拟DOM开始重新渲染和分发,接着调用updated方法完成数据跟新;beforeUpdate不会完成页面的刷新,只有完成updated方法之后才会触发页面刷新

  5.   当vm.destroy方法被调用,这里vm.destroy方法被调用如当页面销毁的时候,系统自动触发,会执行beforeDestroy方法,然后释放一些资源,再调用destroyed方法完整整个生命周期; beforeDestroy函数在实例销毁之前调用。在这一步,实例仍然完全可用。destroyed函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

6. 语法糖

  语法糖我的理解就是代码的简写,编译器帮助我们转换,如ES6中的箭头函数
var add = (a, b) => a + b  //定义一个方法
add(3, 8)  //执行该方法

  在ES5中他的写法为

function add(a,b){
	return a + b;
}

7. NPM install -save 和 -save-dev的区别

   npm install -save moduleName : 将模块安装到项目目录下,并在package文件的dependencies节点写入依赖
     npm install -save-dev moduleName : 将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖

其中dependencies是指生产环境,devDependencies是指开发环境, 举个例子:   项目要依赖于某一个库,没有这个库就会报错,这时候把这个依赖写入dependencies ;但是在发布的时候,如webpack这种构建工具只在开发打包的时候使用,发布的版本不需要他们,所以将它写入devDependencies

  npm install -g moduleName : 将模块进行全局安装,不写入devDependencies和dependencies
  npm install moduleName : 将模块安装到项目模块中,如node_modules文件夹,但是不写入devDependencies和dependencies

8. 自定义Dialog,并在父组件中与其交互

   这里实现的效果是在一个页面中弹出二次确认对话框,点击确认按钮,执行父组件中的方法,点击取消,二次确认框消失;   

    

在这里插入图片描述

具体代码如下:

<!--父组件代码-->

<template>
  <div class="login">
    <button class="showConfimDlg" v-on:click="showConfirmDialog()">打开二次确认对话框</button>
    <!--二次确认对话框,实现该对话框的userBehavior方法来判断点击了哪一个按钮-->
    <confirmSendPackageDlg ref="myConfirm" @userBehavior="userBehaviorFun"></confirmSendPackageDlg>
  </div>
</template>

<script>
import confirmSendPackageDlg from './confirm/confirmDialog'

export default {
  name: 'login-page',
  components: {confirmSendPackageDlg},
  data () {
    return {
    }
  },
  methods: {
    showConfirmDialog () {
      let confirDlg = this.$refs.myConfirm
      confirDlg.show()
    },
    clickOkButton () {
      alert('点击了确认按钮')
    },
    userBehaviorFun (type, data) {
      if (type === 'clickConfirm') {
        this.clickOkButton()
      }
    }
  }
}
</script>

<style>
body {
  font-family: "Source Sans Pro", sans-serif;
  background: #ea5c54;
}
.showConfimDlg{
  width: 200px;
  height: 50px;
  border: 1px solid #FF6699;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto; 
}
</style>

<!--二次确认对话框-->
<template>
  <transition name="confirm-fade">
      <div v-if="isShowConfirm" class="my-confirm">
        <div class="confirm-content-wrap">
        <p class="my-confirm-content">{{ content }}</p>
        <div class="my-operation">
          <div class="my-cancel-btn" @click="clickFun('clickCancel')">
            <p class="my-btn-text my-border-right">{{ cancelText }}</p>
          </div>
          <div class="confirm-btn" @click="clickFun('clickConfirm')">
            <p class="my-btn-text">{{ confirmText }}</p>
          </div>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
/* eslint-disable */
export default {
    name: 'confirmDialog',

    data () {
        return {
            isShowConfirm: false,
            content: '这是二次确认框',
            cancelText: '取消',
            confirmText: '确认',
            //需要传输的数据
            outerData: null
        }
    },
    methods: {
        show () {
            this.isShowConfirm = true
        },
        hidden () {
            this.isShowConfirm = false
        },
        clickFun (type) {
            //子组件使用 $emit 触发父组件的自定义事件
            this.$emit('userBehavior', type, this.outerData)
            this.hidden()
        }
    }
}
</script>

<style scoped>
  .my-confirm {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 998;
    -webkit-text-size-adjust: 100%;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  }

  .confirm-content-wrap {
    position: absolute;
    top: 28%;
    left: 0;
    right: 0;
    width: 280px;
    margin: 0 auto;
    background-color: #fff;
    border-radius: 5px;
    z-index: 999;
    user-select: none;
  }

  .my-confirm-title {
    padding-top: 20px;
    text-align: center;
    font-size: 20px;
    font-weight: 500;
    color: #333;
  }

  .my-confirm-content {
    padding: 0 15px;
    padding-top: 20px;
    margin-bottom: 32px;
    text-align: center;
    font-size: 16px;
    color: #666;
    line-height: 1.5;
  }

  .my-operation {
    display: flex;
    border-top: 1px solid #eee;
  }
  .my-operation .my-cancel-btn, .confirm-btn {
    flex: 1;
  }
  .my-operation .confirm-btn {
    color: #ffb000;
  }
  .my-operation .my-btn-text {
    text-align: center;
    font-size: 16px;
    margin: 14px 0;
    padding: 6px 0;
    cursor: pointer;
  }

  .my-operation .my-btn-text:hover {
    text-align: center;
    font-size: 18px;
    margin: 14px 0;
    padding: 6px 0;
    cursor: pointer;
    background-color: #eeeeee;
  }

  .my-border-right {
    border-right: 1px solid #eee;
  }
</style>

9. ES6中的箭头函数

  箭头函数是一个语法糖,作用是定义函数,基础语法如下
var f = key => value;

  等号后面跟参数,参数可以使用括号,多个参数之间可以使用逗号分隔;箭头后面跟函数的逻辑,如果有多条语句,使用画括号

  上面代码的含义是定义一个方法,其参数为key,返回为value

var  f = function (key) {
        return value;
    }

  在如

 var sum = (num1, num2) => num1 + num2;

  其在ES5中表示

var sum = function (num1, num2) {
        return num1 + num2;
    }

同时我们应该注意一下箭头函数中的this绑定到它的是他的外围作用域

10. 如何在Vue中定义全局变量,全局函数

   在一个Vue项目中,我们也是可以使用js文件的,顾js的一些特性我们都可以使用
  1. 我们首先新建一个globel.js文件,里面是一些全局变量和全局函数
export default{
    videos: '',
    hintInput: '',
    showPasswordInput: '',
    allMenuContents: '',

    isShowMenu(menu) {
        return false
    }
}

   第1行,通过export default会将变量和方法进行导出,这样其他vue组件通过import的方式就可以使用了    第2~第5行,定义了全局变量videos,hintInput,showPasswordInput和allMenuContents,初始值均为空字符串    第7行,定义了全局函数isShowMenu,参数为menu,默认返回false

  1. 然后我们在xxx.vue这个模块中使用globel.js

    2.1 第一步,使用import关键字引入globel.js文件 import global from './globeldata/globel' from后面跟的是globel.js文件所在目录,注意引入的时候不需要添加.js后缀,此时我们就可以通过global来使用global.js中的变量和方法了

    2.2 对global.js中的hintInput赋值 global.hintInput = '请输入密码' 此处我们将全局变量赋值为'请输入密码

    2.3 调用global.js中的全局函数isShowMenu if (!global.isShowMenu('扫描')) {} 此处调用isShowMenu方法,传入参数‘扫描’