diff --git "a/cn/Zadig v4.0/21.\345\274\200\345\217\221\350\200\205\344\270\255\345\277\203/02.idp-manual.md" "b/cn/Zadig v4.0/21.\345\274\200\345\217\221\350\200\205\344\270\255\345\277\203/02.idp-manual.md"
index e488dc232..cbbca7b3c 100644
--- "a/cn/Zadig v4.0/21.\345\274\200\345\217\221\350\200\205\344\270\255\345\277\203/02.idp-manual.md"
+++ "b/cn/Zadig v4.0/21.\345\274\200\345\217\221\350\200\205\344\270\255\345\277\203/02.idp-manual.md"
@@ -210,42 +210,42 @@ export default {
```javascript
// src/index.js
-import React, { useState, useEffect } from 'react';
import './styles.css';
-function MyPluginPage() {
- const [data, setData] = useState([]);
- const [loading, setLoading] = useState(true);
-
- useEffect(() => {
- fetchData();
- }, []);
-
- const fetchData = async () => {
- try {
- const response = await fetch('/api/data');
- const result = await response.json();
- setData(result);
- } catch (error) {
- console.error('Error fetching data:', error);
- } finally {
- setLoading(false);
+const MyPluginPage = {
+ name: 'MyPluginPage',
+ data() {
+ return {
+ data: [],
+ loading: true
+ };
+ },
+ async mounted() {
+ await this.fetchData();
+ },
+ methods: {
+ async fetchData() {
+ try {
+ const response = await fetch('/api/data');
+ const result = await response.json();
+ this.data = result;
+ } catch (error) {
+ console.error('Error fetching data:', error);
+ } finally {
+ this.loading = false;
+ }
}
- };
-
- return (
-
+ },
+ template: `
+
我的插件
- {loading ? (
-
加载中...
- ) : (
-
- {/* 业务逻辑 */}
-
- )}
+
加载中...
+
+
+
- );
-}
+ `
+};
export default {
name: 'my-plugin',
@@ -274,44 +274,52 @@ export default {
```javascript
// src/index.js
-import React, { useState, useEffect } from 'react';
import './styles.css';
-function MyTabComponent({ context }) {
- // context 包含父页面的上下文信息
- // 如:项目名称、环境信息等
- const { projectName, envName } = context || {};
- const [info, setInfo] = useState(null);
-
- useEffect(() => {
- if (projectName) {
- loadProjectInfo(projectName);
+const MyTabComponent = {
+ name: 'MyTabComponent',
+ props: {
+ context: {
+ type: Object,
+ default: () => ({})
}
- }, [projectName]);
-
- const loadProjectInfo = async (name) => {
- try {
- const response = await fetch(`/api/project/${name}`);
- const data = await response.json();
- setInfo(data);
- } catch (error) {
- console.error('Error:', error);
+ },
+ data() {
+ return {
+ info: null
+ };
+ },
+ watch: {
+ 'context.projectName': {
+ handler(newProjectName) {
+ if (newProjectName) {
+ this.loadProjectInfo(newProjectName);
+ }
+ },
+ immediate: true
}
- };
-
- return (
-
+ },
+ methods: {
+ async loadProjectInfo(name) {
+ try {
+ const response = await fetch(`/api/project/${name}`);
+ const data = await response.json();
+ this.info = data;
+ } catch (error) {
+ console.error('Error:', error);
+ }
+ }
+ },
+ template: `
+
项目信息
- {info ? (
-
- {/* 展示项目相关信息 */}
-
- ) : (
-
暂无数据
- )}
+
+
+
+
暂无数据
- );
-}
+ `
+};
export default {
name: 'my-tab-plugin',
@@ -367,8 +375,8 @@ module.exports = {
`src/index.js` 是插件的入口文件:
```javascript
-import React from 'react';
-import App from './App';
+import Vue from 'vue';
+import App from './App.vue';
import './styles/index.css';
// 导出插件配置和组件
@@ -397,21 +405,29 @@ export default {
#### 组件开发
```javascript
-// 使用函数组件和 Hooks
-import React, { useState, useEffect } from 'react';
-
-function MyComponent() {
- const [data, setData] = useState([]);
-
- useEffect(() => {
+// 使用Vue2组件和Options API
+export default {
+ name: 'MyComponent',
+ data() {
+ return {
+ data: []
+ };
+ },
+ async mounted() {
// 数据加载逻辑
- fetchData();
- }, []);
-
- return
{/* 组件内容 */}
;
-}
-
-export default MyComponent;
+ await this.fetchData();
+ },
+ methods: {
+ async fetchData() {
+ // 数据获取逻辑
+ }
+ },
+ template: `
+
+
+
+ `
+};
```
#### 样式管理
@@ -472,80 +488,109 @@ async function fetchData() {
#### 懒加载
```javascript
-// 使用 React.lazy 进行组件懒加载
-const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
-
-function App() {
- return (
-
加载中...}>
+// 使用Vue异步组件进行懒加载
+export default {
+ name: 'App',
+ components: {
+ HeavyComponent: () => import('./HeavyComponent.vue')
+ },
+ template: `
+
-
- );
-}
+
+ `
+};
```
#### 防抖与节流
```javascript
-import { useState, useCallback } from 'react';
-
// 使用 debounce 优化搜索输入
-function SearchInput() {
- const [query, setQuery] = useState('');
-
- const handleSearch = useCallback(
- debounce((value) => {
- // 执行搜索
- performSearch(value);
- }, 300),
- []
- );
-
- return (
+export default {
+ name: 'SearchInput',
+ data() {
+ return {
+ query: '',
+ timer: null
+ };
+ },
+ methods: {
+ handleSearch(value) {
+ // 清除上一次的定时器
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ // 设置新的定时器
+ this.timer = setTimeout(() => {
+ this.performSearch(value);
+ }, 300);
+ },
+ performSearch(value) {
+ // 执行搜索逻辑
+ console.log('搜索:', value);
+ }
+ },
+ template: `
{
- setQuery(e.target.value);
- handleSearch(e.target.value);
- }}
+ v-model="query"
+ @input="handleSearch(query)"
+ placeholder="输入搜索关键词"
/>
- );
-}
+ `
+};
```
### 5. 用户体验
#### 加载状态
```javascript
-function DataList() {
- const [loading, setLoading] = useState(true);
- const [data, setData] = useState([]);
-
- return (
+export default {
+ name: 'DataList',
+ data() {
+ return {
+ loading: true,
+ data: []
+ };
+ },
+ template: `
- {loading ? (
-
加载中...
- ) : (
-
{/* 数据展示 */}
- )}
+
+ 加载中...
+
+
+
+
- );
-}
+ `
+};
```
#### 空状态提示
```javascript
-function DataList({ data }) {
- if (data.length === 0) {
- return (
-
+export default {
+ name: 'DataList',
+ props: {
+ data: {
+ type: Array,
+ default: () => []
+ }
+ },
+ methods: {
+ handleRefresh() {
+ this.$emit('refresh');
+ }
+ },
+ template: `
+
+
- );
- }
-
- return
{/* 数据列表 */}
;
-}
+
+
+
+
+ `
+};
```
### 6. 数据持久化
diff --git a/en/Zadig v4.0/21.Developer Guide/02.idp-manual.md b/en/Zadig v4.0/21.Developer Guide/02.idp-manual.md
index 5b1cb64b5..f9114674a 100644
--- a/en/Zadig v4.0/21.Developer Guide/02.idp-manual.md
+++ b/en/Zadig v4.0/21.Developer Guide/02.idp-manual.md
@@ -210,42 +210,42 @@ export default {
```javascript
// src/index.js
-import React, { useState, useEffect } from 'react';
import './styles.css';
-function MyPluginPage() {
- const [data, setData] = useState([]);
- const [loading, setLoading] = useState(true);
-
- useEffect(() => {
- fetchData();
- }, []);
-
- const fetchData = async () => {
- try {
- const response = await fetch('/api/data');
- const result = await response.json();
- setData(result);
- } catch (error) {
- console.error('Error fetching data:', error);
- } finally {
- setLoading(false);
+const MyPluginPage = {
+ name: 'MyPluginPage',
+ data() {
+ return {
+ data: [],
+ loading: true
+ };
+ },
+ async mounted() {
+ await this.fetchData();
+ },
+ methods: {
+ async fetchData() {
+ try {
+ const response = await fetch('/api/data');
+ const result = await response.json();
+ this.data = result;
+ } catch (error) {
+ console.error('Error fetching data:', error);
+ } finally {
+ this.loading = false;
+ }
}
- };
-
- return (
-
+ },
+ template: `
+
My Plugin
- {loading ? (
-
Loading...
- ) : (
-
- {/* Business logic */}
-
- )}
+
Loading...
+
+
+
- );
-}
+ `
+};
export default {
name: 'my-plugin',
@@ -274,44 +274,52 @@ export default {
```javascript
// src/index.js
-import React, { useState, useEffect } from 'react';
import './styles.css';
-function MyTabComponent({ context }) {
- // context contains parent page context information
- // Such as: project name, environment info, etc.
- const { projectName, envName } = context || {};
- const [info, setInfo] = useState(null);
-
- useEffect(() => {
- if (projectName) {
- loadProjectInfo(projectName);
+const MyTabComponent = {
+ name: 'MyTabComponent',
+ props: {
+ context: {
+ type: Object,
+ default: () => ({})
}
- }, [projectName]);
-
- const loadProjectInfo = async (name) => {
- try {
- const response = await fetch(`/api/project/${name}`);
- const data = await response.json();
- setInfo(data);
- } catch (error) {
- console.error('Error:', error);
+ },
+ data() {
+ return {
+ info: null
+ };
+ },
+ watch: {
+ 'context.projectName': {
+ handler(newProjectName) {
+ if (newProjectName) {
+ this.loadProjectInfo(newProjectName);
+ }
+ },
+ immediate: true
}
- };
-
- return (
-
+ },
+ methods: {
+ async loadProjectInfo(name) {
+ try {
+ const response = await fetch(`/api/project/${name}`);
+ const data = await response.json();
+ this.info = data;
+ } catch (error) {
+ console.error('Error:', error);
+ }
+ }
+ },
+ template: `
+
Project Information
- {info ? (
-
- {/* Display project related information */}
-
- ) : (
-
No data available
- )}
+
+
+
+
No data available
- );
-}
+ `
+};
export default {
name: 'my-tab-plugin',
@@ -367,8 +375,8 @@ module.exports = {
`src/index.js` is the plugin's entry file:
```javascript
-import React from 'react';
-import App from './App';
+import Vue from 'vue';
+import App from './App.vue';
import './styles/index.css';
// Export plugin configuration and component
@@ -397,21 +405,29 @@ export default {
#### Component Development
```javascript
-// Use functional components and Hooks
-import React, { useState, useEffect } from 'react';
-
-function MyComponent() {
- const [data, setData] = useState([]);
-
- useEffect(() => {
+// Use Vue2 components and Options API
+export default {
+ name: 'MyComponent',
+ data() {
+ return {
+ data: []
+ };
+ },
+ async mounted() {
// Data loading logic
- fetchData();
- }, []);
-
- return
{/* Component content */}
;
-}
-
-export default MyComponent;
+ await this.fetchData();
+ },
+ methods: {
+ async fetchData() {
+ // Data fetching logic
+ }
+ },
+ template: `
+
+
+
+ `
+};
```
#### Style Management
@@ -472,80 +488,109 @@ async function fetchData() {
#### Lazy Loading
```javascript
-// Use React.lazy for component lazy loading
-const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
-
-function App() {
- return (
-
Loading...}>
+// Use Vue async components for lazy loading
+export default {
+ name: 'App',
+ components: {
+ HeavyComponent: () => import('./HeavyComponent.vue')
+ },
+ template: `
+
-
- );
-}
+
+ `
+};
```
#### Debounce and Throttle
```javascript
-import { useState, useCallback } from 'react';
-
// Use debounce to optimize search input
-function SearchInput() {
- const [query, setQuery] = useState('');
-
- const handleSearch = useCallback(
- debounce((value) => {
- // Perform search
- performSearch(value);
- }, 300),
- []
- );
-
- return (
+export default {
+ name: 'SearchInput',
+ data() {
+ return {
+ query: '',
+ timer: null
+ };
+ },
+ methods: {
+ handleSearch(value) {
+ // Clear previous timer
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ // Set new timer
+ this.timer = setTimeout(() => {
+ this.performSearch(value);
+ }, 300);
+ },
+ performSearch(value) {
+ // Search logic
+ console.log('Searching:', value);
+ }
+ },
+ template: `
{
- setQuery(e.target.value);
- handleSearch(e.target.value);
- }}
+ v-model="query"
+ @input="handleSearch(query)"
+ placeholder="Enter search keywords"
/>
- );
-}
+ `
+};
```
### 5. User Experience
#### Loading State
```javascript
-function DataList() {
- const [loading, setLoading] = useState(true);
- const [data, setData] = useState([]);
-
- return (
+export default {
+ name: 'DataList',
+ data() {
+ return {
+ loading: true,
+ data: []
+ };
+ },
+ template: `
- {loading ? (
-
Loading...
- ) : (
-
{/* Data display */}
- )}
+
+ Loading...
+
+
+
+
- );
-}
+ `
+};
```
#### Empty State
```javascript
-function DataList({ data }) {
- if (data.length === 0) {
- return (
-
+export default {
+ name: 'DataList',
+ props: {
+ data: {
+ type: Array,
+ default: () => []
+ }
+ },
+ methods: {
+ handleRefresh() {
+ this.$emit('refresh');
+ }
+ },
+ template: `
+
+
No data available
-
+
- );
- }
-
- return
{/* Data list */}
;
-}
+
+
+
+
+ `
+};
```
### 6. Data Persistence