我的第一个项目 :处理全局变量(解决模块化后变量无法获取的问题)

Posted 养肥胖虎

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的第一个项目 :处理全局变量(解决模块化后变量无法获取的问题)相关的知识,希望对你有一定的参考价值。

好家伙,

 

飞机大战分包分的差不多了,

但是又出现了问题:

文件目录如下:

 

然而关于变量

 

 

helloworld.vue完整代码

<template>
  <div>
    <div ref="stage"></div>
  </div>
</template>

<script>
//     Award,
//     Bullet,
//     Enemy,
//     Hero,
//     Loading,
//     Main,
//     Sky
//七个大类引进来
import Award from "./js/award"
import Bullet from "./js/bullet"
import Enemy from "./js/enemy"
import Hero from "./js/hero"
import Loading from "./js/loading"
// import Main from "./js/main"
import Sky from "./js/sky"

// import SKYY from "./js/config"

import  START, STARTING, RUNNING, PAUSE, END, LOADINGING  from "./js/config"
import  SKY, LOADING, HERO, BULLET, E1, E2, E3, C1  from "./js/config"
import  bg, copyright, pause  from "./js/config"
export default 
  mounted() 
    //console测试
    console.log("模块化测试")
    //canvas初始化
    console.log("我被执行啦")
    let canvas = document.createElement(\'canvas\');
    this.$refs.stage.appendChild(canvas);
    canvas.width = 480;
    canvas.height = 650;
    canvas.ref = canvas;
    canvas.style = "border: 1px solid red;"
    const context = canvas.getContext("2d");
    //state表示游戏的状态 取值必须是以上的五种状态
    let state = START;

    //score 分数变量 life 变量
    let score = 0;
    let life = 3;

    //初始化奖励类
    // class Loading 
    //   constructor(config) 
    //     this.frame = config.frame;
    //     this.img = this.frame;
    //     this.frameIndex = 0;
    //     this.width = config.width;
    //     this.height = config.height;
    //     this.x = config.x;
    //     this.y = config.y;
    //     this.speed = config.speed;
    //     this.lastTime = new Date().getTime();
    //   
    //   judge() 
    //     const currentTime = new Date().getTime();
    //     if (currentTime - this.lastTime > this.speed) 
    //       this.frameIndex++;
    //       if (this.frameIndex === 4) 
    //         state = RUNNING;
    //       
    //       this.lastTime = currentTime;
    //     
    //   
    //   paint(context) 
    //     if (this.frameIndex < 3)
    //       context.drawImage(this.img[this.frameIndex], this.x, this.y);
    //   
    // 
    class Main 
      //一下全为全局变量或方法 (全局的!!)
      //初始化一个天空实例
      //主启动方法
      maingame() 
        const sky = new Sky(SKY);
        //初始化一个飞机界面加载实例
        const loading = new Loading(LOADING);
        loading.prototype =this;
        
        //初始化一个英雄实例 英雄是会变的
        let hero = new Hero(HERO);
        //该变量中有所有的敌机实例
        let enemies = [];
        //该变量中存放所有的奖励实例

        let awards = [];
        //敌机产生的速率
        let ENEMY_CREATE_INTERVAL = 800;
        let ENEMY_LASTTIME = new Date().getTime();

        function stateControl() 
          //为canvas绑定一个点击事件 且他如果是START状态的时候需要修改成STARTING状态
          canvas.addEventListener("click", () => 
            if (state === START) 
              state = STARTING;
            
          );
          // 为canvas绑定一个鼠标移动事件 鼠标正好在飞机图片的正中心
          canvas.addEventListener("mousemove", (e) => 
            let x = e.offsetX;
            let y = e.offsetY;
            hero.x = x - hero.width / 2;
            hero.y = y - hero.height / 2;
          );
          // 为canvas绑定一个鼠标离开事件 鼠标离开时 RUNNING -> PAUSE
          canvas.addEventListener("mouseleave", () => 
            if (state === RUNNING) 
              state = PAUSE;
            
          );
          // 为canvas绑定一个鼠标进入事件 鼠标进入时 PAUSE => RUNNING
          canvas.addEventListener("mouseenter", () => 
            if (state === PAUSE) 
              state = RUNNING;
            
          );
          //为canvas绑定一个屏幕移动触摸点事件 触碰点正好在飞机图片的正中心
          canvas.addEventListener("touchmove", (e) => 
            // let x = e.pageX;
            // let y = e.pageY;
            console.log(e);
            // let x = e.touches[0].clientX;
            // let y = e.touches[0].clinetY;
            let x = e.touches[0].pageX;
            let y = e.touches[0].pageY;
            // let x = e.touches[0].screenX;
            // let y = e.touches[0].screenY;
            let write1 = (document.body.clientWidth - 480) / 2;
            let write2 = (document.body.clientHeight - 650) / 2;
            hero.x = x - write1 - hero.width / 2;
            hero.y = y - write2 - hero.height / 2;

            // hero.x = x - hero.width / 2;
            // hero.y = y - hero.height / 2;
            console.log(x, y);
            console.log(document.body.clientWidth, document.body.clientHeight);
            e.preventDefault(); // 阻止屏幕滚动的默认行为

          )
        
        stateControl();
        // 碰撞检测函数
        //此处的碰撞检测包括 
        //1.子弹与敌机的碰撞
        //2.英雄与敌机的碰撞
        //3.英雄与随机奖励的碰撞
        function checkHit() 
          // 遍历所有的敌机
          for (let i = 0; i < awards.length; i++) 
            //检测英雄是否碰到奖励类
            if (awards[i].hit(hero)) 
              //当然了,这个随机奖励的样式也要删了
              awards.splice(i, 1);
              //清除所有的敌机
              // for (let i = 0; i < enemies.length; i++) 
              //   enemies.splice(i, 1);
              // 
              enemies.length = 0;

            
          
          for (let i = 0; i < enemies.length; i++) 
            //检测英雄是否撞到敌机
            if (enemies[i].hit(hero)) 
              //将敌机和英雄的destory属性改为true
              enemies[i].collide();
              hero.collide();
            
            for (let j = 0; j < hero.bulletList.length; j++) 
              enemies[i].hit(hero.bulletList[j]);
              //检测子弹是否撞到敌机
              if (enemies[i].hit(hero.bulletList[j])) 
                //将敌机和子弹的destory属性改为true
                enemies[i].collide();
                hero.bulletList[j].collide();
              
            
          
        
        // 全局函数 隔一段时间就来初始化一架敌机/奖励
        function createComponent() 
          const currentTime = new Date().getTime();
          if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) 
            let ran = Math.floor(Math.random() * 100);
            if (ran < 55) 
              enemies.push(new Enemy(E1));
             else if (ran < 85 && ran > 55) 
              enemies.push(new Enemy(E2));
             else if (ran < 95 && ran > 85) 
              enemies.push(new Enemy(E3));
             else if (ran > 95) 
              awards.push(new Award(C1));

            

            ENEMY_LASTTIME = currentTime;
          
        
        // 全局函数 来判断所有的子弹/敌人组件 "负责移动"
        function judgeComponent() 
          for (let i = 0; i < hero.bulletList.length; i++) 
            hero.bulletList[i].move();
          
          for (let i = 0; i < enemies.length; i++) 
            enemies[i].move();
          
          for (let i = 0; i < awards.length; i++) 
            awards[i].move();
          
        
        // 全局函数 来绘制所有的子弹/敌人组件 绘制score&life面板
        function paintComponent() 
          for (let i = 0; i < hero.bulletList.length; i++) 
            hero.bulletList[i].paint(context);
          
          for (let i = 0; i < enemies.length; i++) 
            enemies[i].paint(context);
          
          for (let i = 0; i < awards.length; i++) 
            awards[i].paint(context);
          
          context.font = "20px 微软雅黑";
          context.fillStyle = "green";
          context.textAlign = "left";
          context.fillText("score: " + score, 10, 20);
          context.textAlign = "right";
          context.fillText("life: " + life, 480 - 10, 20);
          //重置样式
          context.fillStyle = "black";
          context.textAlign = "left";
        
        // 全局函数 来销毁所有的子弹/敌人组件 销毁掉英雄
        function deleteComponent() 
          if (hero.destory) 
            life--;
            hero.destory = false;
            if (life === 0) 
              state = END;
             else 
              hero = new Hero(HERO);
            
          
          for (let i = 0; i < hero.bulletList.length; i++) 
            if (hero.bulletList[i].outOfBounds() || hero.bulletList[i].destory) 
              hero.bulletList.splice(i, 1);
            
          
          for (let i = 0; i < enemies.length; i++) 
            if (enemies[i].outOfBounds() || enemies[i].destory) 
              enemies.splice(i, 1);
            
          
        

        //当图片加载完毕时,需要做某些事情
        bg.addEventListener("load", () => 
          setInterval(() => 
            switch (state) 
              case START:
                sky.judge();
                sky.paint(context);
                let logo_x = (480 - copyright.naturalWidth) / 2;
                let logo_y = (650 - copyright.naturalHeight) / 2;
                context.drawImage(copyright, logo_x, logo_y);
                break;
              case STARTING:
                sky.judge();
                sky.paint(context);
                loading.judge();
                loading.paint(context);
                break;
              case RUNNING:
                sky.judge();
                sky.paint(context);
                hero.judge();
                hero.paint(context);
                hero.shoot(context);
                createComponent();
                judgeComponent();
                deleteComponent();
                paintComponent();
                checkHit();
                break;
              case PAUSE:
                let pause_x = (480 - pause.naturalWidth) / 2;
                let pause_y = (650 - pause.naturalHeight) / 2;
                context.drawImage(pause, pause_x, pause_y);
                break;
              case END:
                //给我的画笔设置一个字的样式
                //后面写出来的字都是这个样式的
                context.font = "bold 24px 微软雅黑";
                context.textAlign = "center";
                context.textBaseline = "middle";
                context.fillText("GAME_OVER", 480 / 2, 650 / 2);
                break;
            
          , 10);
        );
      
    

    let main_1 = new Main()
    main_1.maingame();
  



</script>

<style>
#stage 
  width: 480px;
  height: 650px;
  margin: 0 auto;

</style>
helloworld.vue

 

来看helloworld.vue中的部分代码

import Loading from "./js/loading"
/**
*
*
**/
let state = START;

const loading = new Loading(LOADING);
/**
*
*
**/
loading.judge();

 

loading.js

// import  state  from "./config"
// 初始化一个飞机界面加载类

import  RUNNING  from "./config";
class Loading 
  constructor(config) 

    this.frame = config.frame;
    this.img = this.frame;
    this.frameIndex = 0;
    this.width = config.width;
    this.height = config.height;
    this.x = config.x;
    this.y = config.y;
    this.speed = config.speed;
    this.lastTime = new Date().getTime();
  
  judge() 
    const currentTime = new Date().getTime();
    if (currentTime - this.lastTime > this.speed) 
      this.frameIndex++;
      if (this.frameIndex === 4) 
        state = RUNNING;
      
      this.lastTime = currentTime;
    
  
  paint(context) 
    if (this.frameIndex < 3) 
      context.drawImage(this.img[this.frameIndex], this.x, this.y);
    
  


export default Loading

 

若我把Loading这个类写在Helloworld.vue中,是不会有报错的,

但我把Loading这个类写在外部的.js文件,然后再使用模块化导入,

可见,es6模块化把原先的作用域分隔开了

 

那么这个问题怎么解决呢?

同时我还有另外两个全局变量life(生命值)和score(分数)要处理

//state表示游戏的状态 取值必须是以上的五种状态
    let state = START;

    //score 分数变量 life 变量
    let score = 0;
  let life = 3;

只能委屈一下window了,把他们都变成全局变量

 //state表示游戏的状态 取值必须是以上的五种状态
    window.state = START;

    //score 分数变量 life 变量
    window.score = 0;
  window.life = 3;

 

搞定,不报错了

 

在vue项目中 如何定义全局变量 全局函数

如题,在项目中,经常有些函数和变量是需要复用,比如说网站服务器地址,从后台拿到的:用户的登录token,用户的地址信息等,这时候就需要设置一波全局变量和全局函数

定义全局变量

原理:

设置一个专用的的全局变量模块文件,模块里面定义一些变量初始状态,用export default 暴露出去,在main.js里面使用Vue.prototype挂载到vue实例上面或者在其它地方需要使用时,引入该模块便可。

全局变量模块文件:

Global.vue文件:

技术图片
<script>
const serverSrc=‘www.baidu.com‘;
const token=‘12345678‘;
const hasEnter=false;
const userSite="中国钓鱼岛";
  export default
  
    userSite,//用户地址
    token,//用户token身份
    serverSrc,//服务器地址
    hasEnter,//用户登录状态
  
</script>
技术图片

使用方式1:

在需要的地方引用进全局变量模块文件,然后通过文件里面的变量名字获取全局变量参数值。

在text1.vue组件中使用:

技术图片
<template>
    <div> token </div>
</template>

<script>
import global_ from ‘../../components/Global‘//引用模块进来
export default 
 name: ‘text‘,
data () 
    return 
         token:global_.token,//将全局变量赋值到data里面,也可以直接使用global_.token
        
    

</script>
<style lang="scss" scoped>

</style>
技术图片

使用方式2:

在程序入口的main.js文件里面,将上面那个Global.vue文件挂载到Vue.prototype。

 import global_ from ‘./components/Global‘//引用文件
 Vue.prototype.GLOBAL = global_//挂载到Vue实例上面

接着在整个项目中不需要再通过引用Global.vue模块文件,直接通过this就可以直接访问Global文件里面定义的全局变量。

text2.vue:

技术图片
<template>
    <div> token </div>
</template>

<script>
export default 
 name: ‘text‘,
data () 
    return 
         token:this.GLOBAL.token,//直接通过this访问全局变量。
        
    

</script>
<style lang="scss" scoped>
</style>
技术图片

Vuex也可以设置全局变量

 

定义全局函数

原理

新建一个模块文件,然后在main.js里面通过Vue.prototype将函数挂载到Vue实例上面,通过this.函数名,来运行函数。

1. 在main.js里面直接写函数

简单的函数可以直接在main.js里面直接写

Vue.prototype.changeData = function ()//changeData是函数名
  alert(‘执行成功‘);

组件中调用:

this.changeData();//直接通过this运行函数

2. 写一个模块文件,挂载到main.js上面。

base.js文件,文件位置可以放在跟main.js同一级,方便引用

技术图片
exports.install = function (Vue, options) 
   Vue.prototype.text1 = function ()//全局函数1
    alert(‘执行成功1‘);
    ;
    Vue.prototype.text2 = function ()//全局函数2
    alert(‘执行成功2‘);
    ;
;
技术图片

main.js入口文件:

import base from ‘./base‘//引用
Vue.use(base);//将全局函数当做插件来进行注册

组件里面调用:

this.text1();
this.text2();

上面就是如何定义全局变量 全局函数的内容了,这里的全局变量全局函数可以不局限于vue项目,vue-cli是用了webpack做模块化,其他模块化开发,定义全局变量、函数的套路基本上是差不多。上文只是对全局变量

以上是关于我的第一个项目 :处理全局变量(解决模块化后变量无法获取的问题)的主要内容,如果未能解决你的问题,请参考以下文章

Keil中C语言模块化编程时全局变量、结构体处理细节

Nodejs全局安装模块后找不到命令的解决方法

python中的多处理模块和修改共享的全局变量

各种模块化简介及演变过程

在vue项目中 如何定义全局变量 全局函数

在vue项目中 如何定义全局变量 全局函数