用React Native制作一个简单的游戏引擎


Posted in Javascript onMay 27, 2021

简介

今天我们将学习如何使用React Native制作一个游戏。因为我们使用的是React Native,这个游戏将是跨平台的,这意味着你可以在Android、iOS和网络上玩同一个游戏。然而,今天我们将只关注移动设备。所以我们开始吧。

开始吧

要制作任何游戏,我们需要一个循环,在我们玩的时候更新我们的游戏。这个循环被优化以顺利运行游戏,为此我们将使用 React Native游戏引擎

首先让我们用以下命令创建一个新的React Native应用。

npx react-native init ReactNativeGame

创建项目后,我们需要添加一个依赖项,以便添加游戏引擎。

npm i -S react-native-game-engine

这个命令将把React Native游戏引擎添加到我们的项目中。

那么,我们要做一个什么样的游戏呢?为了简单起见,让我们做一个蛇的游戏,它可以吃食物的碎片并增长身长。

对React Native游戏引擎的简单介绍

React Native Game Engine是一个轻量级的游戏引擎。它包括一个组件,允许我们将对象的数组添加为实体,这样我们就可以对它们进行操作。为了编写我们的游戏逻辑,我们使用了一个系统道具阵列,它允许我们操纵实体(游戏对象),检测触摸,以及许多其他令人敬畏的细节,帮助我们制作一个简单的、功能性的游戏。

让我们在React Native中建立一个蛇形游戏

要制作一个游戏,我们需要一个画布或容器,我们将在其中添加游戏对象。要制作一个画布,我们只需添加一个带有风格的视图组件,像这样。

// App.js     
<View style={styles.canvas}>
</View>

我们可以像这样添加我们的样式。

const styles = StyleSheet.create({
  canvas: {
    flex: 1,
    backgroundColor: "#000000",
    alignItems: "center",
    justifyContent: "center",
  }
});

在画布中,我们将使用 GameEngine 组件和一些来自React Native Game Engine的样式。

import { GameEngine } from "react-native-game-engine";
import React, { useRef } from "react";
import Constants from "./Constants";


export default function App() {
  const BoardSize = Constants.GRID_SIZE * Constants.CELL_SIZE;
  const engine = useRef(null);
  return (
    <View style={styles.canvas}>
      <GameEngine
              ref={engine}
              style={{
                width: BoardSize,
                height: BoardSize,
                flex: null,
                backgroundColor: "white",
              }}
            />
    </View>
);

我们还使用 useRef() React Hook为游戏引擎添加了一个ref,以便日后使用。

我们还在项目的根部创建了一个 Constants.js 文件来存储我们的常量值。

// Constants.js
import { Dimensions } from "react-native";
export default {
  MAX_WIDTH: Dimensions.get("screen").width,
  MAX_HEIGHT: Dimensions.get("screen").height,
  GRID_SIZE: 15,
  CELL_SIZE: 20
};

你会注意到我们正在做一个15乘15的网格,我们的蛇将在那里移动。

这时我们的游戏引擎已经设置好了,以显示蛇和它的食物。我们需要将实体和道具添加到 GameEngine ,但在此之前,我们需要创建一个蛇和食物的组件,在设备上渲染。

创建游戏实体

让我们首先制作蛇。蛇分为两部分,头部和身体(或尾巴)。现在我们将制作蛇的头部,我们将在本教程的后面添加蛇的尾巴。

为了制作蛇的头部,我们将在组件文件夹中制作一个 Head 组件。

正如你所看到的,我们有三个组件: Head , Food ,和 Tail 。我们将在本教程中逐一查看这些文件的内容。

在 Head 组件中,我们将创建一个带有一些样式的视图。

import React from "react";
import { View } from "react-native";
export default function Head({ position, size }) {
  return (
    <View
      style={{
        width: size,
        height: size,
        backgroundColor: "red",
        position: "absolute",
        left: position[0] * size,
        top: position[1] * size,
      }}
    ></View>
  );
}

我们将传递一些道具来设置头部的大小和位置。

我们使用 position: "absolute" 属性来轻松移动头部。

这将呈现一个正方形,我们不打算使用更复杂的东西;一个正方形或长方形的形状代表蛇的身体,一个圆形的形状代表食物。

现在让我们将这条蛇的头部添加到 GameEngine 。

要添加任何实体,我们需要在 GameEngine 中的 entities 道具中传递一个对象。

//App.js
import Head from "./components/Head";


 <GameEngine
        ref={engine}
        style={{
          width: BoardSize,
          height: BoardSize,
          flex: null,
          backgroundColor: "white",
        }}
        entities={{
          head: {
            position: [0, 0],
            size: Constants.CELL_SIZE,
            updateFrequency: 10,
            nextMove: 10,
            xspeed: 0,
            yspeed: 0,
            renderer: <Head />,
          }
        }} 
/>

我们在 entities 道具中传递了一个对象,其关键是头。这些是它定义的属性。

  • position 是一组坐标,用于放置蛇头。
  • size 是设置蛇头大小的值。
  • xspeedyspeed 是决定蛇的运动和方向的值,可以是1、0或-1。注意,当 xspeed 被设置为1或-1时,那么 yspeed 的值必须为0,反之亦然
  • 最后, renderer ,负责渲染该组件
  • updateFrequencynextMove 将在后面讨论。

在添加完 Head 组件后,我们也来添加其他组件。

// commponets/Food/index.js
import React from "react";
import { View } from "react-native";
export default function Food({ position, size }) {
  return (
    <View
      style={{
        width: size,
        height: size,
        backgroundColor: "green",
        position: "absolute",
        left: position[0] * size,
        top: position[1] * size,
        borderRadius: 50
      }}
    ></View>
  );
}

Food 组件与 Head 组件类似,但我们改变了背景颜色和边框半径,使其成为一个圆形。

现在创建一个 Tail 组件。这个可能很棘手。

// components/Tail/index.js

import React from "react";
import { View } from "react-native";
import Constants from "../../Constants";
export default function Tail({ elements, position, size }) {
  const tailList = elements.map((el, idx) => (
    <View
      key={idx}
      style={{
        width: size,
        height: size,
        position: "absolute",
        left: el[0] * size,
        top: el[1] * size,
        backgroundColor: "red",
      }}
    />
  ));
  return (
    <View
      style={{
        width: Constants.GRID_SIZE * size,
        height: Constants.GRID_SIZE * size,
      }}
    >
      {tailList}
    </View>
  );
}

当蛇吃了食物后,我们将在蛇身中添加一个元素,这样我们的蛇就会成长。这些元素将传入 Tail 组件,这将表明它必须变大。

我们将循环浏览所有的元素来创建整个蛇身,附加上它,然后渲染。

在制作完所有需要的组件后,让我们把这两个组件作为 GameEngine 。

// App.js

import Food from "./components/Food";
import Tail from "./components/Tail";


// App.js
const randomPositions = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1) + min);
  };


// App.js

<GameEngine
        ref={engine}
        style={{
          width: BoardSize,
          height: BoardSize,
          flex: null,
          backgroundColor: "white",
        }}
        entities={{
          head: {
            position: [0, 0],
            size: Constants.CELL_SIZE,
            updateFrequency: 10,
            nextMove: 10,
            xspeed: 0,
            yspeed: 0,
            renderer: <Head />,
          },
          food: {
            position: [
              randomPositions(0, Constants.GRID_SIZE - 1),
              randomPositions(0, Constants.GRID_SIZE - 1),
            ],
            size: Constants.CELL_SIZE,
            renderer: <Food />,
          },
          tail: {
            size: Constants.CELL_SIZE,
            elements: [],
            renderer: <Tail />,
          },
        }}

      />

为了保证食物位置的随机性,我们做了一个带有最小和最大参数的 randomPositions 函数。

在 tail ,我们在初始状态下添加了一个空数组,所以当蛇吃到食物时,它将在 elements: 空间中存储每个尾巴的长度。

在这一点上,我们已经成功创建了我们的游戏组件。现在是在游戏循环中添加游戏逻辑的时候了。

游戏逻辑

为了使游戏循环, GameEngine 组件有一个叫 systems 的道具,它接受一个数组的函数。

为了保持一切结构化,我正在创建一个名为 systems 的文件夹,并插入一个名为 GameLoop.js 的文件。

在这个文件中,我们正在导出一个带有某些参数的函数。

// GameLoop.js

export default function (entities, { events, dispatch }) {
  ...

  return entities;
}

第一个参数是 entities ,它包含了我们传递给 GameEngine 组件的所有实体,所以我们可以操作它们。另一个参数是一个带有属性的对象,即 events 和 dispatch 。

移动蛇头

让我们编写代码,将蛇头向正确的方向移动。

在 GameLoop.js 函数中,我们将更新头部的位置,因为这个函数在每一帧都会被调用。

// GameLoop.js
export default function (entities, { events, dispatch }) {
  const head = entities.head;
  head.position[0] += head.xspeed;
  head.position[1] += head.yspeed;
}

我们使用 entities 参数访问头部,在每一帧中我们都要更新蛇头的位置。

如果你现在玩游戏,什么也不会发生,因为我们把 xspeed 和 yspeed 设置为0。如果你把 xspeed 或 yspeed 设置为1,蛇的头部会移动得很快。

为了减慢蛇的速度,我们将像这样使用 nextMove 和 updateFrequency 的值。

const head = entities.head;

head.nextMove -= 1;
if (head.nextMove === 0) {
  head.nextMove = head.updateFrequency;

  head.position[0] += head.xspeed;
  head.position[1] += head.yspeed;
}

我们通过在每一帧中减去1来更新 nextMove 的值为0。当值为0时, if 条件被设置为 true , nextMove 值被更新回初始值,从而移动蛇的头部。

现在,蛇的速度应该比以前慢了。

"游戏结束!"条件

在这一点上,我们还没有添加 "游戏结束!"条件。第一个 "游戏结束!"条件是当蛇碰到墙时,游戏停止运行,并向用户显示一条信息,表明游戏已经结束。

为了添加这个条件,我们使用这段代码。

if (head.nextMove === 0) {
  head.nextMove = head.updateFrequency;
  if (
        head.position[0] + head.xspeed < 0 ||
        head.position[0] + head.xspeed >= Constants.GRID_SIZE ||
        head.position[1] + head.yspeed < 0 ||
        head.position[1] + head.yspeed >= Constants.GRID_SIZE
      ) {
        dispatch("game-over");
      } else {
        head.position[0] += head.xspeed;
        head.position[1] += head.yspeed;
    }

第二个 if 条件是检查蛇头是否触及墙壁。如果该条件为真,那么我们将使用 dispatch 函数来发送一个 "game-over" 事件。

通过 else ,我们正在更新蛇的头部位置。

现在让我们添加 "游戏结束!"的功能。

每当我们派发一个 "game-over" 事件时,我们将停止游戏,并显示一个警告:"游戏结束!"让我们来实现它。

为了监听 "game-over" 事件,我们需要将 onEvent 道具传递给 GameEngine 组件。为了停止游戏,我们需要添加一个 running 道具并传入 useState 。

我们的 GameEngine 应该看起来像这样。

// App.js
import React, { useRef, useState } from "react";
import GameLoop from "./systems/GameLoop";

....
....

const [isGameRunning, setIsGameRunning] = useState(true);

....
....

 <GameEngine
        ref={engine}
        style={{
          width: BoardSize,
          height: BoardSize,
          flex: null,
          backgroundColor: "white",
        }}
        entities={{
          head: {
            position: [0, 0],
            size: Constants.CELL_SIZE,
            updateFrequency: 10,
            nextMove: 10,
            xspeed: 0,
            yspeed: 0,
            renderer: <Head />,
          },
          food: {
            position: [
              randomPositions(0, Constants.GRID_SIZE - 1),
              randomPositions(0, Constants.GRID_SIZE - 1),
            ],
            size: Constants.CELL_SIZE,
            renderer: <Food />,
          },
          tail: {
            size: Constants.CELL_SIZE,
            elements: [],
            renderer: <Tail />,
          },
        }}
        systems={[GameLoop]}
        running={isGameRunning}
        onEvent={(e) => {
          switch (e) {
            case "game-over":
              alert("Game over!");
              setIsGameRunning(false);
              return;
          }
        }}
      />

在 GameEngine 中,我们已经添加了 systems 道具,并通过我们的 GameLoop 函数传入了一个数组,同时还有一个 running 道具和一个 isGameRunning 状态。最后,我们添加了 onEvent 道具,它接受一个带有事件参数的函数,这样我们就可以监听我们的事件。

在这种情况下,我们在switch语句中监听 "game-over" 事件,所以当我们收到该事件时,我们显示 "Game over!" 警报,并将 isGameRunning 状态设置为 false ,以停止游戏。

食用食物

我们已经写好了 "游戏结束!"的逻辑,现在让我们来写一下让蛇吃食物的逻辑。

当蛇吃了食物后,食物的位置应该随机变化。

打开 GameLoop.js ,写下以下代码。

// GameLoop.js

const randomPositions = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1) + min);
};

export default function (entities, { events, dispatch }) {
  const head = entities.head;
  const food = entities.food;

  ....
  ....
  ....
  if (
        head.position[0] + head.xspeed < 0 ||
        head.position[0] + head.xspeed >= Constants.GRID_SIZE ||
        head.position[1] + head.yspeed < 0 ||
        head.position[1] + head.yspeed >= Constants.GRID_SIZE
      ) {
        dispatch("game-over");
      } else {

     head.position[0] += head.xspeed;
     head.position[1] += head.yspeed;

     if (
          head.position[0] == food.position[0] &&
          head.position[1] == food.position[1]
        ) {

          food.position = [
            randomPositions(0, Constants.GRID_SIZE - 1),
            randomPositions(0, Constants.GRID_SIZE - 1),
          ];
        }
  }

我们添加了一个 if ,以检查蛇头和食物的位置是否相同(这将表明蛇已经 "吃 "了食物)。然后,我们使用 randomPositions 函数更新食物的位置,正如我们在上面的 App.js 。请注意,我们是通过 entities 参数来访问食物的。

控制蛇

现在让我们来添加蛇的控制。我们将使用按钮来控制蛇的移动位置。

要做到这一点,我们需要在画布下面的屏幕上添加按钮。

// App.js

import React, { useRef, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import { GameEngine } from "react-native-game-engine";
import { TouchableOpacity } from "react-native-gesture-handler";
import Food from "./components/Food";
import Head from "./components/Head";
import Tail from "./components/Tail";
import Constants from "./Constants";
import GameLoop from "./systems/GameLoop";
export default function App() {
  const BoardSize = Constants.GRID_SIZE * Constants.CELL_SIZE;
  const engine = useRef(null);
  const [isGameRunning, setIsGameRunning] = useState(true);
  const randomPositions = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1) + min);
  };
  const resetGame = () => {
    engine.current.swap({
      head: {
        position: [0, 0],
        size: Constants.CELL_SIZE,
        updateFrequency: 10,
        nextMove: 10,
        xspeed: 0,
        yspeed: 0,
        renderer: <Head />,
      },
      food: {
        position: [
          randomPositions(0, Constants.GRID_SIZE - 1),
          randomPositions(0, Constants.GRID_SIZE - 1),
        ],
        size: Constants.CELL_SIZE,
        updateFrequency: 10,
        nextMove: 10,
        xspeed: 0,
        yspeed: 0,
        renderer: <Food />,
      },
      tail: {
        size: Constants.CELL_SIZE,
        elements: [],
        renderer: <Tail />,
      },
    });
    setIsGameRunning(true);
  };
  return (
    <View style={styles.canvas}>
      <GameEngine
        ref={engine}
        style={{
          width: BoardSize,
          height: BoardSize,
          flex: null,
          backgroundColor: "white",
        }}
        entities={{
          head: {
            position: [0, 0],
            size: Constants.CELL_SIZE,
            updateFrequency: 10,
            nextMove: 10,
            xspeed: 0,
            yspeed: 0,
            renderer: <Head />,
          },
          food: {
            position: [
              randomPositions(0, Constants.GRID_SIZE - 1),
              randomPositions(0, Constants.GRID_SIZE - 1),
            ],
            size: Constants.CELL_SIZE,
            renderer: <Food />,
          },
          tail: {
            size: Constants.CELL_SIZE,
            elements: [],
            renderer: <Tail />,
          },
        }}
        systems={[GameLoop]}
        running={isGameRunning}
        onEvent={(e) => {
          switch (e) {
            case "game-over":
              alert("Game over!");
              setIsGameRunning(false);
              return;
          }
        }}
      />
      <View style={styles.controlContainer}>
        <View style={styles.controllerRow}>
          <TouchableOpacity onPress={() => engine.current.dispatch("move-up")}>
            <View style={styles.controlBtn} />
          </TouchableOpacity>
        </View>
        <View style={styles.controllerRow}>
          <TouchableOpacity
            onPress={() => engine.current.dispatch("move-left")}
          >
            <View style={styles.controlBtn} />
          </TouchableOpacity>
          <View style={[styles.controlBtn, { backgroundColor: null }]} />
          <TouchableOpacity
            onPress={() => engine.current.dispatch("move-right")}
          >
            <View style={styles.controlBtn} />
          </TouchableOpacity>
        </View>
        <View style={styles.controllerRow}>
          <TouchableOpacity
            onPress={() => engine.current.dispatch("move-down")}
          >
            <View style={styles.controlBtn} />
          </TouchableOpacity>
        </View>
      </View>
      {!isGameRunning && (
        <TouchableOpacity onPress={resetGame}>
          <Text
            style={{
              color: "white",
              marginTop: 15,
              fontSize: 22,
              padding: 10,
              backgroundColor: "grey",
              borderRadius: 10
            }}
          >
            Start New Game
          </Text>
        </TouchableOpacity>
      )}
    </View>
  );
}
const styles = StyleSheet.create({
  canvas: {
    flex: 1,
    backgroundColor: "#000000",
    alignItems: "center",
    justifyContent: "center",
  },
  controlContainer: {
    marginTop: 10,
  },
  controllerRow: {
    flexDirection: "row",
    justifyContent: "center",
    alignItems: "center",
  },
  controlBtn: {
    backgroundColor: "yellow",
    width: 100,
    height: 100,
  },
});

除了控制之外,我们还添加了一个按钮,以便在前一个游戏结束时开始一个新的游戏。这个按钮只在游戏没有运行时出现。在点击该按钮时,我们通过使用游戏引擎的 swap 函数来重置游戏,传入实体的初始对象,并更新游戏的运行状态。

现在说说控制。我们已经添加了可触摸物体,当按下这些物体时,就会派发将在游戏循环中处理的事件。

// GameLoop.js
....
....
 export default function (entities, { events, dispatch }) {
    const head = entities.head;
    const food = entities.food;

  if (events.length) {
    events.forEach((e) => {
      switch (e) {
        case "move-up":
          if (head.yspeed === 1) return;
          head.yspeed = -1;
          head.xspeed = 0;
          return;
        case "move-right":
          if (head.xspeed === -1) return;
          head.xspeed = 1;
          head.yspeed = 0;
          return;
        case "move-down":
          if (head.yspeed === -1) return;
          head.yspeed = 1;
          head.xspeed = 0;
          return;
        case "move-left":
          if (head.xspeed === 1) return;
          head.xspeed = -1;
          head.yspeed = 0;
          return;
      }
    });
  }

....
....
});

在上面的代码中,我们添加了一个 switch 语句来识别事件并更新蛇的方向。

还在听我说吗?很好!唯一剩下的就是尾巴了。

尾巴功能

当蛇吃了食物后,我们希望它的尾巴能长出来。我们还想在蛇咬到自己的尾巴或身体时发出一个 "游戏结束!"的事件。

让我们来添加尾巴逻辑。

// GameLoop.js

const tail = entities.tail;

....
....

....

    else {
      tail.elements = [[head.position[0], head.position[1]], ...tail.elements];
      tail.elements.pop();

      head.position[0] += head.xspeed;
      head.position[1] += head.yspeed;

      tail.elements.forEach((el, idx) => {
        if (
          head.position[0] === el[0] &&
          head.position[1] === el[1] 
        )
          dispatch("game-over");
      });
      if (
        head.position[0] == food.position[0] &&
        head.position[1] == food.position[1]
      ) {
        tail.elements = [
          [head.position[0], head.position[1]],
          ...tail.elements,
        ];

        food.position = [
          randomPositions(0, Constants.GRID_SIZE - 1),
          randomPositions(0, Constants.GRID_SIZE - 1),
        ];
      }
    }

为了使尾巴跟随蛇的头部,我们要更新尾巴的元素。我们通过将头部的位置添加到元素数组的开头,然后删除尾巴元素数组上的最后一个元素来实现这一目的。

在这之后,我们写一个条件,如果蛇咬了自己的身体,我们就分派 "game-over" 事件。

最后,每当蛇吃了食物,我们就用蛇头的当前位置来追加蛇尾的元素,以增加蛇尾的长度。

下面是 GameLoop.js 的完整代码。

// GameLoop.js

import Constants from "../Constants";
const randomPositions = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1) + min);
};
  export default function (entities, { events, dispatch }) {
    const head = entities.head;
    const food = entities.food;
    const tail = entities.tail;
  if (events.length) {
    events.forEach((e) => {
      switch (e) {
        case "move-up":
          if (head.yspeed === 1) return;
          head.yspeed = -1;
          head.xspeed = 0;
          return;
        case "move-right":
          if (head.xspeed === -1) return;
          head.xspeed = 1;
          head.yspeed = 0;
          // ToastAndroid.show("move right", ToastAndroid.SHORT);
          return;
        case "move-down":
          if (head.yspeed === -1) return;
          // ToastAndroid.show("move down", ToastAndroid.SHORT);
          head.yspeed = 1;
          head.xspeed = 0;
          return;
        case "move-left":
          if (head.xspeed === 1) return;
          head.xspeed = -1;
          head.yspeed = 0;
          // ToastAndroid.show("move left", ToastAndroid.SHORT);
          return;
      }
    });
  }
  head.nextMove -= 1;
  if (head.nextMove === 0) {
    head.nextMove = head.updateFrequency;
    if (
      head.position[0] + head.xspeed < 0 ||
      head.position[0] + head.xspeed >= Constants.GRID_SIZE ||
      head.position[1] + head.yspeed < 0 ||
      head.position[1] + head.yspeed >= Constants.GRID_SIZE
    ) {
      dispatch("game-over");
    } else {
      tail.elements = [[head.position[0], head.position[1]], ...tail.elements];
      tail.elements.pop();
      head.position[0] += head.xspeed;
      head.position[1] += head.yspeed;
      tail.elements.forEach((el, idx) => {
        console.log({ el, idx });
        if (
          head.position[0] === el[0] &&
          head.position[1] === el[1] 
        )
          dispatch("game-over");
      });
      if (
        head.position[0] == food.position[0] &&
        head.position[1] == food.position[1]
      ) {
        tail.elements = [
          [head.position[0], head.position[1]],
          ...tail.elements,
        ];

        food.position = [
          randomPositions(0, Constants.GRID_SIZE - 1),
          randomPositions(0, Constants.GRID_SIZE - 1),
        ];
      }
    }
  }
  return entities;
}

结语

现在你的第一个React Native游戏已经完成了你可以在自己的设备上运行这个游戏来玩。我希望你能学到一些新的东西,也希望你能与你的朋友分享。

谢谢你的阅读,祝你有个愉快的一天。

The post How to build a simple game in React Native appeared first onLogRocket Blog .

以上就是用React Native构建一个简单的游戏的详细内容,更多关于React Native游戏的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
用循环或if语句从json中取数据示例
Aug 18 Javascript
跟我学习javascript的函数和函数表达式
Nov 16 Javascript
浅谈JS原型对象和原型链
Mar 02 Javascript
AngularJs Modules详解及示例代码
Sep 01 Javascript
解决Angular.Js与Django标签冲突的方案
Dec 20 Javascript
浅谈jQuery的bind和unbind事件(绑定和解绑事件)
Mar 02 Javascript
js如何编写简单的ajax方法库
Aug 02 Javascript
jQuery EasyUI window窗口使用实例代码
Dec 25 jQuery
vue实现点击关注后及时更新列表功能
Jun 26 Javascript
详解Vue的钩子函数(路由导航守卫、keep-alive、生命周期钩子)
Jul 24 Javascript
详解easyui 切换主题皮肤
Apr 04 Javascript
jQuery+ajax实现用户登录验证
Sep 13 jQuery
Vue实现动态查询规则生成组件
QT与javascript交互数据的实现
May 26 #Javascript
小程序实现筛子抽奖
详解vue身份认证管理和租户管理
ES6 解构赋值的原理及运用
vue点击弹窗自动触发点击事件的解决办法(模拟场景)
js Proxy的原理详解
May 25 #Javascript
You might like
php error_log 函数的使用
2009/04/13 PHP
php中防止恶意刷新页面的代码小结
2012/10/31 PHP
使用PHP强制下载PDF文件示例
2014/01/17 PHP
php把数据表导出为Excel表的最简单、最快的方法(不用插件)
2014/05/10 PHP
Yii2实现多域名跨域同步登录退出
2017/02/04 PHP
javascript 正则替换 replace(regExp, function)用法
2010/05/22 Javascript
javascript面向对象编程代码
2011/12/19 Javascript
Jquery插件写法笔记整理
2012/09/06 Javascript
js中判断用户输入的值是否为空的简单实例
2013/12/23 Javascript
javascript函数定义的几种区别小结
2014/01/06 Javascript
javascript继承机制实例详解
2014/11/20 Javascript
JQuery仿小米手机抢购页面倒计时效果
2014/12/16 Javascript
JavaScript 异常处理 详解
2015/02/06 Javascript
js针对ip地址、子网掩码、网关的逻辑性判断
2016/01/06 Javascript
Backbone.js框架中简单的View视图编写学习笔记
2016/02/14 Javascript
JQuery的常用选择器、过滤器、方法全面介绍
2016/05/25 Javascript
jQuery ui autocomplete选择列表被Bootstrap模态窗遮挡的完美解决方法
2016/09/23 Javascript
扩展jquery easyui tree的搜索树节点方法(推荐)
2016/10/28 Javascript
简单实现js悬浮导航效果
2017/02/05 Javascript
详解JS异步加载的三种方式
2017/03/07 Javascript
使用NestJS开发Node.js应用的方法
2018/12/03 Javascript
vue设计一个倒计时秒杀的组件详解
2019/04/06 Javascript
少女风vue组件库的制作全过程
2019/05/15 Javascript
[52:26]完美世界DOTA2联赛决赛 FTD vs Phoenix 第一场 11.08
2020/11/11 DOTA
django.db.utils.ProgrammingError: (1146, u“Table‘’ doesn’t exist”)问题的解决
2018/07/13 Python
Python爬虫运用正则表达式的方法和优缺点
2019/08/25 Python
Window10下python3.7 安装与卸载教程图解
2019/09/30 Python
Python Serial串口基本操作(收发数据)
2020/11/06 Python
LookFantastic丹麦:英国美容护肤精品在线商城
2016/08/18 全球购物
Tenstickers法国:墙贴和装饰贴纸
2019/08/26 全球购物
中式面点餐厅创业计划书
2014/01/29 职场文书
活动总结结尾怎么写
2014/08/30 职场文书
不听老师话的万能检讨书
2014/10/04 职场文书
高中化学教学反思
2016/02/22 职场文书
详解TypeScript的基础类型
2022/02/18 Javascript
Redis sentinel哨兵集群的实现步骤
2022/07/15 Redis