# 将业务逻辑从 UI 组件中分离出来

Copilot Chat 可以帮助你将业务逻辑与用户界面代码分开，从而更轻松地维护和缩放应用程序。

在许多前端框架中，业务逻辑可能会嵌入到用户界面 (UI) 组件内，这使得代码难以维护或扩展，尤其是在应用程序不断发展的过程中。

Copilot Chat 可帮助你重构代码，将业务逻辑提取到单独的服务或状态管理解决方案中。 这使得业务逻辑能够在不同的 UI 组件中重复使用。 通过分离关注点并减少相互依赖关系，这也使得代码更易于缩放，而且通过允许业务逻辑独立于 UI 组件进行测试，还简化了单元测试。

## 示例方案

在这段 JavaScript 代码中，`Counter` 组件为该组件配置业务逻辑，并且还定义了在网页中使用该组件的 UI 代码。

```javascript id=counter-component
import React, { useState } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    if (count >= 10) {
      alert('Count cannot exceed 10');
      return;
    }
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default Counter;
```

## 示例提示

```copilot copy prompt ref=counter-component
Use Redux to separate the UI code from the Counter component in this code.
```

## 示例响应

Copilot 提供重构代码的分步说明。

建议的更改对 `Counter` 组件进行重构，以使用 Redux 进行状态管理。 这包括设置一个带有初始状态和一个归约器的 Redux 存储，定义一个递增操作，并修改 `Counter` 组件以连接到 Redux 存储。 最后，使用 `Provider` 组件包装应用程序，以便向 `Counter` 组件提供 Redux 存储区。 这会将 UI 逻辑与状态管理分开。

建议的更改将代码分成五个单独的文件。

> \[!NOTE]
> Copilot Chat 响应是不确定的，因此你可能会得到与此处所述的响应不同的响应。

### actions.js

```javascript
export const increment = () => ({
  type: 'INCREMENT'
});
```

### reducer.js

```javascript
const initialState = {
  count: 0
};

const counterReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'INCREMENT':
      if (state.count >= 10) {
        alert('Count cannot exceed 10');
        return state;
      }
      return {
        ...state,
        count: state.count + 1
      };
    default:
      return state;
  }
};

export default counterReducer;
```

### store.js

```javascript
import { createStore } from 'redux';
import counterReducer from './reducer';

const store = createStore(counterReducer);

export default store;
```

### counter.js

```javascript
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './actions';

const Counter = () => {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => dispatch(increment())}>Increment</button>
    </div>
  );
};

export default Counter;
```

### index.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './counter';

ReactDOM.render(
  <Provider store={store}>
    <Counter />
  </Provider>,
  document.getElementById('root')
);
```

## 延伸阅读

* [GitHub Copilot 对话助手的提示设计](/zh/copilot/concepts/prompting/prompt-engineering)
* [使用 GitHub Copilot 的最佳做法](/zh/copilot/get-started/best-practices)