# 场景系统

PE引擎的场景系统是其核心特性之一，它提供了一种结构化的方式来组织和管理应用的不同视图和状态。每个场景都是一个独立的单元，包含模板、样式和逻辑代码。

## 场景的基本结构

PE场景由三个主要部分组成：

1. **模板（Template）** - 定义场景的结构和元素
2. **样式（Style）** - 定义场景的外观和样式
3. **脚本（Script）** - 定义场景的逻辑和行为

### 场景文件结构

一个典型的PE场景目录结构如下：

```
scenes/
├── home/
│   ├── index.pe      # 场景模板文件
│   └── index.less    # 场景样式文件
└── about/
    ├── index.pe
    └── index.less
```

## 场景模板文件（.pe）

场景模板文件使用类似HTML的语法，包含`sence`标签和`script`标签：

```html
<sence>
  <!-- 场景元素定义 -->
  <sprite class="logo"></sprite>
  <box class="welcome-box">欢迎来到PE引擎!</box>
  <text class="description">这是一个简单的场景示例</text>
  
  <!-- 循环渲染元素 -->
  <box for="{item} in menuItems" 
       class="menu-item" 
       @click="handleMenuClick(item.id)">
    {{ item.label }}
  </box>
</sence>

<script>
// 场景数据和逻辑
const menuItems = [
  { id: 'home', label: '首页' },
  { id: 'about', label: '关于' },
  { id: 'contact', label: '联系' }
]

// 生命周期钩子
onLoad(() => {
  console.log('场景加载完成')
})

onShow(() => {
  console.log('场景显示')
})

// 事件处理函数
function handleMenuClick(id) {
  console.log('点击了菜单项:', id)
  PE.navigateTo(`/${id}`)
}
</script>
```

### 模板语法

PE场景模板支持以下语法特性：

#### 元素定义

```html
<!-- 基本元素 -->
<sprite class="my-sprite" x="100" y="100" width="50" height="50"></sprite>
<box class="my-box">盒子内容</box>
<text class="my-text">文本内容</text>
```

#### 事件绑定

使用`@`前缀绑定事件处理器：

```html
<box @click="handleClick" @mouseenter="handleMouseEnter">点击我</box>
```

#### 循环渲染

使用`for`指令循环渲染元素：

```html
<box for="{item} in items" class="item">{{ item.name }}</box>
```

#### 插值表达式

使用双大括号语法插入数据：

```html
<text>当前计数: {{ count }}</text>
```

## 场景样式文件（.less）

每个场景可以有对应的Less样式文件，样式会自动作用于该场景内的元素：

```less
// home/index.less
.logo {
  width: 100px;
  height: 100px;
  background-color: #3498db;
  border-radius: 50%;
  position: absolute;
  top: 50px;
  left: 50px;
}

.welcome-box {
  width: 300px;
  height: 100px;
  background-color: #2c3e50;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 200px;
  left: 50px;
  border-radius: 8px;
}

.description {
  color: #7f8c8d;
  font-size: 16px;
  position: absolute;
  top: 320px;
  left: 50px;
}

.menu-item {
  width: 150px;
  height: 40px;
  background-color: #e74c3c;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  left: 50px;
  border-radius: 4px;
  cursor: pointer;
  
  // 使用Less变量和嵌套
  &:hover {
    background-color: darken(#e74c3c, 10%);
  }
  
  &:nth-child(1) { top: 380px; }
  &:nth-child(2) { top: 430px; }
  &:nth-child(3) { top: 480px; }
}
```

## 场景路由配置

场景通过`sences.json`文件进行路由配置：

```json
{
  "sence": [
    {
      "path": "/",
      "title": "首页"
    },
    {
      "path": "/about",
      "title": "关于我们"
    },
    {
      "path": "/products",
      "title": "产品"
    }
  ],
  "platform": "PC"
}
```

## 场景生命周期

每个场景都有完整的生命周期钩子，让你能够在适当的时机执行操作：

### onLoad

场景加载时调用，只在场景首次加载时执行一次：

```javascript
onLoad(() => {
  console.log('场景加载完成')
  // 初始化操作
  initializeData()
})
```

### onShow

场景显示时调用，每次场景被显示时都会执行：

```javascript
onShow(() => {
  console.log('场景显示')
  // 每次显示时的操作
  refreshData()
})
```

### onHide

场景隐藏时调用：

```javascript
onHide(() => {
  console.log('场景隐藏')
  // 清理操作
  pauseAnimations()
})
```

### onDestory

场景销毁时调用：

```javascript
onDestory(() => {
  console.log('场景销毁')
  // 最终清理操作
  clearInterval(timer)
})
```

## 场景间导航

PE提供了简单的API来在场景间进行导航：

```javascript
// 导航到指定路径的场景
PE.navigateTo('/about')

// 在模板中使用
<box @click="PE.navigateTo('/products')">查看产品</box>
```

## 完整示例

以下是一个完整的场景示例：

### scenes/product/index.pe

```html
<sence>
  <box class="header">产品列表</box>
  
  <box for="{product} in products" 
       class="product-card" 
       @click="viewProduct(product.id)">
    <text class="product-name">{{ product.name }}</text>
    <text class="product-price">¥{{ product.price }}</text>
  </box>
  
  <box class="back-button" @click="PE.navigateTo('/')">返回首页</box>
</sence>

<script>
// 产品数据
const products = [
  { id: 1, name: '产品A', price: 99.99 },
  { id: 2, name: '产品B', price: 149.99 },
  { id: 3, name: '产品C', price: 199.99 }
]

// 生命周期钩子
onLoad(() => {
  console.log('产品页面加载')
})

onShow(() => {
  console.log('产品页面显示')
})

// 事件处理函数
function viewProduct(id) {
  console.log('查看产品:', id)
  // 可以通过全局变量或事件传递数据
  window.currentProductId = id
  PE.navigateTo('/product-detail')
}
</script>
```

### scenes/product/index.less

```less
.header {
  width: 100%;
  height: 60px;
  background-color: #34495e;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: bold;
}

.product-card {
  width: 300px;
  height: 100px;
  background-color: #ecf0f1;
  border: 1px solid #bdc3c7;
  border-radius: 8px;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 20px;
  cursor: pointer;
  
  &:hover {
    background-color: #d5dbdb;
  }
  
  &:nth-child(2) { top: 100px; }  // 第一个产品卡
  &:nth-child(3) { top: 220px; }  // 第二个产品卡
  &:nth-child(4) { top: 340px; }  // 第三个产品卡
}

.product-name {
  color: #2c3e50;
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 5px;
}

.product-price {
  color: #e74c3c;
  font-size: 16px;
  font-weight: bold;
}

.back-button {
  width: 100px;
  height: 40px;
  background-color: #95a5a6;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  bottom: 20px;
  left: 20px;
  border-radius: 4px;
  cursor: pointer;
  
  &:hover {
    background-color: #7f8c8d;
  }
}
```

通过以上内容，你已经了解了PE引擎的场景系统。在下一章节中，我们将探讨样式处理的相关内容。