이 글에서 공유한 내용은 Pastate.js 반응형 반응 프레임워크의 양식 렌더링 및 작동에 관한 것입니다. 이는 특정 참조 값을 가지고 있습니다. 필요한 친구는 이를 참조할 수 있습니다.
Pasate.js 반응형 반응 상태 관리입니다. 프레임워크 튜토리얼 시리즈의 네 번째 장입니다. 관심을 갖고 계속 업데이트해 주시기 바랍니다. Pastate.js Github
이번 장에서는 Pastate에서 폼 요소를 렌더링하고 조작하는 방법을 살펴보겠습니다.
기본 양식 요소 사용
BasicInfoView
구성 요소의 두 버튼 아래에 이름을 입력할 수 있는 입력 상자를 추가하고, 성별을 선택할 수 있는 확인란을 추가합니다. BasicInfoView
组件的两个按钮下面添加一个输入框用于输入姓名,并添加一个勾选框用于选择性别,更改如下:
class BasicInfoView extends PureComponent { render() { ... return ( <p style={{ padding: 10, margin: 10 }}> ... <p> <button onClick={this.decreaseAge}> decrease age </button> <button onClick={this.increaseAge}> increase age </button> </p> <p> name: <input type="text" value={state.name} onChange={this.handleNameChange}/> <br /> Is boy: <input type="checkbox" checked={state.isBoy == true} onChange={this.handleIsBoyChange}/> </p> </p> ) } }
上面添加两个了 input 标签,第一个 input 使用 name 数据, 第二个 input 使用 isBoy 数据。同时我们也先指定两个 input 的 onChange 处理函数。
注意:如前面章节所提及,对于 imState 布尔值,请记得使用显式布尔值方式:checked={state.isBoy == true}
。
接下来看看如何实现两个 onChange 处理函数:
class BasicInfoView extends PureComponent { ... handleNameChange(e){ state.basicInfo.name = e.target.value store.sync() // 编辑中的输入框,需手动同步store } handleIsBoyChange(e){ state.basicInfo.isBoy = e.target.checked } ... }
非常熟悉和简单!你只需把更新的值赋给目标state节点即可。我们会发现多了个 store.sync()
,这个函数是让 pastate 立刻执行数据同步更新。由于很多输入法会在输入过程中会把带下划线的 “拼音字母” 输入到 input 中,如下:
如果 pastate 执行异步更新会使带下划线 “拼音字母” 中断,因此我们在更新 编辑中的输入框 时,需要简单地使用 store.sync()
执行同步更新,让 “拼音” 连续。如果不是对 编辑中的输入框 进行修改或不需要支持输入法输入(如密码等),无需使用 store.sync()
。
初步完成!我们试着往输入框输入文字,或点击勾选框, 可以看到文字区域的值与 input 区域的视图都正常地进行更新!
与普通 react 表单的处理模式一样,我们可以通过 onChange 函数的实时控制输入的内容,如转化大小写、控制字符串长度等:
class BasicInfoView extends PureComponent { ... // 把输入值都转化为大写 handleNameChange_uppercase(e){ state.basicInfo.name = e.target.value.toUpperCase() store.sync() } // 控制文本长度在10个字符以内 handleNameChange_limitedLength(e){ if(e.target.value.length > 10) return; state.basicInfo.name = e.target.value store.sync() } ... }
使用 pastate 双向绑定输入组件
使用过 vue.js 或 angular.js 的人都体验过自动双向数据绑定 (two-ways data binding) 的便捷性,但由于 react state 渲染的单向数据流原则,在 react 中没有默认提供这个功能。而 pastate 的 imState 具有保存节点信息的特殊性,能够很容易实现自动双向数据绑定功能!
pastate 为你提供了四个已实现双向数据绑定的高阶表单组件 (Higher Order Component, 通常简称 HOC) ,这些组件都是基于 PureComponent 实现的,具有良好的渲染性能,你可以尽情享用他们!这四个表单组件如下:
Input
: 文本框Checkbox
: 复选框RadioGroup
: 单选框选项组-
Select
import { ..., Input } from 'pastate' ... render(){ let state = this.props.state return( ... <Input value={state.text1} /> {/** 单行输入框,内部使用 <input type="text" /> 实现 */} <Input value={state.text2} type="textarea" /> {/** 多行输入框,内部使用 <textarea /> 实现 */} ... ) } ...
위에 두 개의 입력 태그가 추가되었습니다. 첫 번째 입력은 이름 데이터를 사용하고 두 번째 입력은 isBoy 데이터를 사용합니다. 동시에 두 입력의 onChange 핸들러 함수도 먼저 지정합니다.
참고: 이전 장에서 언급한 것처럼 imState 부울 값의 경우 명시적인 부울 값 방법(checked={state.isBoy == true}
)을 사용해야 합니다.
...
handleTextBeforeChange(newValue, oldValue) {
// 把输入的字符转化为大写
return newValue.toUpperCase()
}
render(){
let state = this.props.state
return(
...
<Input value={state.text1} beforeChange={this.handleTextBeforeChange} />
...
)
}
...
매우 친숙하고 간단합니다! 업데이트된 값을 대상 상태 노드에 할당하기만 하면 됩니다. 추가 store.sync()
가 있음을 알 수 있습니다. 이 함수를 사용하면 데이터 동기화 업데이트를 즉시 수행할 수 있습니다. 많은 입력 방법이 입력 과정에서 입력에 밑줄이 그어진 "병음 문자"를 입력하기 때문에 다음과 같습니다:

store.sync()
를 사용하여 동기 업데이트를 수행하여 "병음"을 연속적으로 만들기만 하면 됩니다. 편집 시 입력 상자를 수정하지 않거나 입력 방법 입력(예: 비밀번호 등)을 지원할 필요가 없는 경우에는 store.sync() . <p></p>첫번째 완료! 입력창에 텍스트를 입력해 보거나, 체크박스를 클릭하면 텍스트 영역의 값과 입력 영역의 뷰가 정상적으로 업데이트되는 것을 확인할 수 있습니다! <ul class=" list-paddingleft-2"><li>일반 반응 형식의 처리 모드와 동일하게 onChange 함수를 통해 대소문자 변환, 문자열 길이 제어 등 입력 내용을 실시간으로 제어할 수 있습니다. <table><pre class='brush:php;toolbar:false;'>import { ..., Checkbox } from &#39;pastate&#39;
...
render(){
let state = this.props.state
return(
...
I am a boy: <Checkbox value={state.isBoy} />
...
)
}
...</pre><tbody>paste를 사용하여 입력 구성 요소를 두 개로 바인딩합니다. 방향<tr class="firstRow"></tr>vue.js나 angle.js를 사용하는 사람들은 자동 양방향 데이터 바인딩(two-ways data Binding)의 편리함을 경험했지만, 반응 상태 렌더링의 단방향 데이터 흐름 원칙으로 인해 이 기능은 그렇지 않습니다. 반응에서 기본적으로 제공됩니다. 페이스트의 imState는 노드 정보를 저장한다는 특징을 가지고 있으며 자동 양방향 데이터 바인딩을 쉽게 구현할 수 있습니다! </tbody>
</table>pastate는 양방향 데이터 바인딩을 구현한 4개의 Higher Order Form 컴포넌트(Higher Order Component, 일반적으로 HOC라고 함)를 제공합니다. 이러한 컴포넌트는 PureComponent를 기반으로 구현되며 좋은 렌더링 성능을 제공합니다. 당신이 좋아하는만큼! 네 가지 양식 구성 요소는 다음과 같습니다. 🎜🎜🎜🎜<code>Input
: 텍스트 상자 🎜🎜🎜🎜Checkbox
: 확인란 🎜🎜🎜🎜RadioGroup
: 라디오 버튼 옵션 그룹🎜🎜🎜🎜선택
: 드롭다운 선택 상자🎜🎜🎜🎜입력 텍스트 상자🎜🎜입력 구성 요소를 사용하여 한 줄 입력 상자와 여러 줄 입력 상자를 표시할 수 있습니다. 바인딩할 값을 전달하기만 하면 됩니다. 인터페이스를 통해 입력 상자의 값을 변경하면 입력 구성 요소가 자동으로 바인딩 상태를 업데이트합니다. 🎜import { ..., RadioGroup } from 'pastate' const goodNames = ['Peter', 'Tom', 'Allen'] ... render(){ let state = this.props.state return( ... Choose a name: <RadioGroup options={goodNames} value={state.name}/> ... ) } ...🎜입력 구성 요소의 속성과 설명은 다음과 같습니다. : 🎜🎜속성 | 값 설명🎜 🎜🎜🎜🎜🎜🎜🎜🎜
value | string | number , 必填 | 绑定的值,需要使用 this.props.state 中的节点 , 即 imState
type | "text" | "textarea" | "password" | "number" | 输入框类型,默认为 "text"
beforeChange | (newValue: string | number, oldValue: string | number) => string | number | 在绑定值更新前会被调用,可用于实现自定义字符串更新逻辑, 如控制大小写或限制字符串长度等;返回值为最终要更新的值
afterChange | (newValue: string | number) => void | 在绑定值更新后会被调用
disabled | boolean | 指定输入框是否处于禁止状态,默认为 false
className | string | 传递给输入框的 class 名 ( 用于指定 css 样式等 )
id | string | 传递给输入框的 id 名 ( 用于指定 css 样式等 )
useComposedValue | boolean | [ 实验特性 ] 指定是否在输入法完成拼音过程时才更新 state 的模式,开启后,在输入拼音的过程中绑定的值不会更新,默认为 false
Input 组件实现了自动绑定数据双向绑定功能,如果你需要自定义字符串更新逻辑,或者在字符值更新后做一些操作,可以通过指定可选的 beforeChange 函数和 afterChange 函数来实现。
... handleTextBeforeChange(newValue, oldValue) { // 把输入的字符转化为大写 return newValue.toUpperCase() } render(){ let state = this.props.state return( ... <Input value={state.text1} beforeChange={this.handleTextBeforeChange} /> ... ) } ...
Input 组件的属性 useComposedValue 开启后,可以实现在输入法输入拼音的过程中绑定的值不会更新的功能,等拼音输入完成后 state 值才更新,减少拼音输入过程中不必要的 state 更新和视图渲染动作:
useComposedValue 属性目前为实验特性,如果发现在某个浏览器或某种输入法中有问题,欢迎提交 issue 。
Checkbox 复选框
每个 Checkbox 是一个勾选框组件,只需传递要绑定的布尔值 state 节点,即可完成绑定:
import { ..., Checkbox } from 'pastate' ... render(){ let state = this.props.state return( ... I am a boy: <Checkbox value={state.isBoy} /> ... ) } ...
Checkbox 组件的属性及其说明如下:
属性 | 值 | 说明
value | boolean,必填 | 绑定的数据值,可直接传入 this.props.state 中的节点值,无需做 state.xxx == true
转化。
afterChange | (newValue: boolean) => void | 在绑定值更新后会被调用
disabled | boolean | 指定禁止点击状态,默认为 false
className | string | 传递 class 名 ( 用于指定 css 样式等 )
id | string | 传递 id 名 ( 用于指定 css 样式等 )
RadioGroup 单选框选项组
RadioGroup 是一个单选框选项组,只要传入选项数组 options 常数和要绑定的选项值 value, 即可完成绑定:
import { ..., RadioGroup } from 'pastate' const goodNames = ['Peter', 'Tom', 'Allen'] ... render(){ let state = this.props.state return( ... Choose a name: <RadioGroup options={goodNames} value={state.name}/> ... ) } ...
RadioGroup 组件的属性及其说明如下:
属性 | 值 | 说明
options | Array
value | string | number | boolean,必填 | 绑定的选中值
disabled | boolean | 指定禁止选择状态,默认为 false
vertical | boolean | 指定选项为垂直排列状态,默认为 false
afterChange | (newValue: string | number | boolean) => void | 在绑定值更新后会被调用
id | string | 传递给选项组根元素的 id
className | string | 传递给选项组根元素的 className
radioClassName | string | 传递给圆形按钮的 className
tagClassName | string | 传递给选项标签的 className
disabledTagClassName | string | 传递给禁用状态的选项标签的附加的 className
options 属性接受两种格式的选项数据格式:
// 简单格式: Array<string> const nameOptions = ['Peter', 'Tom', 'Allen'] // 完备格式: Array<{value: string, tag: string, disabled?: boolean}> const nameOptionsChinese = [{ value: 'Peter', // 数据值 tag: '彼得', // 选项标签值 disabled: true // 可选地指定某个选项为不可选 },{ value: 'Tom', tag: '汤姆' },{ value: 'Allen', tag: '艾伦' }]
RadioGroup
是基于 PureComponent 实现的,对于 options 属性的值,建议定义一个 文件级 的选项数组常量, 这样可以提高渲染效率。如果把 options 值定义在 render 函数里或写成直接赋值的匿名对象(<radiogroup options='{["a",' ...></radiogroup>
), 在每次父组件渲染时,无论绑定的 value 数据有没有更新,RadioGroup 获取到的 options 属性的引用值都不一样,会使 RadioGroup 进行多余的渲染动作。 当你使用其他基于 PureComponent 实现的组件时,在向其传递数组 / 对象类型的常量的时候也可以做这样的性能优化。
Select 下拉选择框
Select 是一个选择框组件,使用方法与 RadioGroup 类似,只要传入选项数组和要绑定的选择值即可完成绑定:
import { ..., Select } from 'pastate' const nameOptionsChinese = [{ value: 'DEFAULT', tag: '请选择', disabled: true },{ value: 'Peter', tag: '彼得' }, { value: 'Tom', tag: '汤姆' }, { value: 'Allen', tag: '艾伦' }] ... render(){ let state = this.props.state return( ... Choose a name: <Select options={nameOptionsChinese} value={state.name}/> ... ) } ...
Seclect 组件的属性及其说明如下:
属性 | 值 | 说明
options | Array
value | string | number | boolean,必填 | 绑定的选中值
disabled | boolean | 指定禁止点击状态,默认为 false
afterChange | (newValue: string | number | boolean) => void | 在绑定值更新后会被调用
id | string | 传递的 id
className | string | 传递的 className
如有需要显示没有选择的状态,可以多设置一个选项元素,通过元素的 tag 设置其提示文本, 并把元素的 disabled 设为 true 即可,没选中时的 value 值自行定义,不可为 null 或 undefined:
const nameOptionsChinese = [{ value: 'DEFAULT', tag: '请选择', disabled: true }, ... ]
Seclect 组件目前仅支持最常用的单选功能,以后将支持多选功能。
pastate 表单组件的类型定义
Pastate 的高阶组件均是使用 Typescript 进行开发 , 提供完整的类型定义文件,当你在 javascript 项目使用它们时,也可以得到良好的组件属性 intelliSense 类型提示:
你也可以右键点击组件名,选择转到类型定义
, 查看组件的所有属性声明:
上图的 type 属性的类型是枚举字符串,在输入时,你可以在空双括号中按下 vsCode 的 “触发提示” 快捷键(具体快捷键因不同系统操作系统和不同设置而异,请到编辑器的 “首选项->设置快捷方式” 处查看,该功能很实用):
对现有组件库进行双向数据绑定
很多时候,我们会使用 react 视图组件库来开发应用,如 ant.design、 material-ui 等,pastate 为这些现有的视图组件提供两个数据双向绑定方法!下面我们以 ant.design 的 Rate 星级评分组件为例进行介绍。
使用 Bind 高阶组件
你可以使用 pastate 提供的 Bind 组件去包围一个原始的视图组件,实现双向数据绑定。
我们先简单地安装 ant.design 组件库: $ npm install antd --save
或 $ yarn add antd
,引入 Rate 组件,并使用 Bind 组件进行包装,实现双向数据绑定:
import { ..., Bind } from 'pastate'; import Rate from 'antd/lib/rate'; import 'antd/lib/rate/style/css'; // 或经过简单配置后,使用 import { Rate } from 'antd', 详见 ant.design 文档 ... // 我们使用 state.basicInfo.age 数据进行演示 class BasicInfoView extends PureComponent { ... render() { /** @type {initState['basicInfo']} */ let state = this.props.state; return ( <p style={{ padding: 10, margin: 10 }}> ... <p> 年龄(Bind): <Bind value={state.age} > <Rate /> </Bind> </p> ... </p> ) } }
我们使用 Bind 组件对 Rate 组件进行包装,并把本来需要传递给 Rate 组件的 value 值传递通过 Bind 组件进行传递,这样就实现了双向数据绑定!如果我们要传递其他属性值给 Rate, 可以不通过 Bind 直接传递给 Rate,如下:
... <Bind value={state.age} > <Rate count={10} /> {/* 根据 ant design 文档, count 属性指定采用 n 级评分 */} </Bind> ...
这样我们就实现了对 Rate 进行双向数据绑定:
你可以通过点击 Rate 组件的星星或点击 descrease age
,increase age
按钮对年龄值进行改变,可以发现当通过按钮更新数据时,Rate 组件可以正确响应。而且 Bind 是一个关于 value 的纯组件,当其他无关数据发生改变时,Bind 元素不会发生多余的渲染动作。
Bind 元素还有两个可选的属性:
valueProp: 指定被包装的组件接收数据的属性名,默认是
value
, 绝大多数组件也是用value
,因此无需指定该值。如果被包装的组件使用的是checked
或其他属性名接收数据值,那么请把 Bind 元素的 valueProp 设为对应的checked
或其他属性名。afterChange: 当组件绑定的值通过该组件发生改变后,会调用该函数,该函数的签名为
(newValue) => void
。当绑定的属性值不是通过该组件发生改变时,afterChange 函数不会被调用。
使用 makeBindable 函数
你也可以使用 makeBindable(RawComponent, valueProp = 'value')
函数生成一个可以复用的可绑定组件:
import { ..., makeBindable } from 'pastate'; ... // 使用 makeBindable 生成对应的可以绑定数据的 Rate 组件 const MyRate = makeBindable(Rate) class BasicInfoView extends PureComponent { ... render() { /** @type {initState['basicInfo']} */ let state = this.props.state; return ( <p style={{ padding: 10, margin: 10 }}> ... <p> 年龄(makeBindable): <MyRate count={10} value={state.age}/> </p> ... </p> ) } }
你可以通过 makeBindable 函数的第二个参数指定 valueProp 值,如 const MyCheckbox = makeBindable(Checkbox, 'checked')
, 同样,你可以通过新组件的 afterChange 属性去响应组件值更新后的个性化操作。
对于绑定的值为空的情况
无论使用 pastate 的表单输入组件还是包装现有的组件库,对于组件绑定的数据值,不支持被设为 null 值 或 undefind 值。通常情况下,我们不会有这种需求。如果需要实现表单的“未选择”状态, 我们一般通过设置一个默认值且不可选的 default 值来代替。例如有个表单需要选择性别,并且需要一个未选择的状态,这样使用一个 RadioGroup 组件来实现:
let initState = { sex: '' // 用字符串表示性别,并设置为选择状态是的值为空字符串 '' 或 'default' } const sexOptions = ['boy', 'girl'] // 只包含目标值 ... render(){ let state = this.props.state; return <RadioGroup options={sexOptions} value={state.sex} /> } ...
如果你的需求场景一定要用到 null 或 undefined 值,欢迎在 issues 中分享。 Pastate 能实现绑定的值支持空值,但如果这个需求只有在非常特殊的情况下才用到,我们就暂不把它默认实现在 pastate 库中,因为这会增加计算量,你可以自行实现这个特殊组件的数据绑定逻辑。
下一章,我们来看看 pastate 应用如何进行模块化。
相关推荐:
Pastate.js 之响应式 react state 管理框架
위 내용은 Pastate.js 반응형 반응 프레임워크 양식 렌더링 및 작업의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

예, JavaScript의 엔진 코어는 C로 작성되었습니다. 1) C 언어는 효율적인 성능과 기본 제어를 제공하며, 이는 JavaScript 엔진 개발에 적합합니다. 2) V8 엔진을 예를 들어, 핵심은 C로 작성되며 C의 효율성 및 객체 지향적 특성을 결합하여 C로 작성됩니다.

JavaScript는 웹 페이지의 상호 작용과 역학을 향상시키기 때문에 현대 웹 사이트의 핵심입니다. 1) 페이지를 새로 고치지 않고 콘텐츠를 변경할 수 있습니다. 2) Domapi를 통해 웹 페이지 조작, 3) 애니메이션 및 드래그 앤 드롭과 같은 복잡한 대화식 효과를 지원합니다. 4) 성능 및 모범 사례를 최적화하여 사용자 경험을 향상시킵니다.

C 및 JavaScript는 WebAssembly를 통한 상호 운용성을 달성합니다. 1) C 코드는 WebAssembly 모듈로 컴파일되어 컴퓨팅 전력을 향상시키기 위해 JavaScript 환경에 도입됩니다. 2) 게임 개발에서 C는 물리 엔진 및 그래픽 렌더링을 처리하며 JavaScript는 게임 로직 및 사용자 인터페이스를 담당합니다.

JavaScript는 웹 사이트, 모바일 응용 프로그램, 데스크탑 응용 프로그램 및 서버 측 프로그래밍에서 널리 사용됩니다. 1) 웹 사이트 개발에서 JavaScript는 HTML 및 CSS와 함께 DOM을 운영하여 동적 효과를 달성하고 jQuery 및 React와 같은 프레임 워크를 지원합니다. 2) 반응 및 이온 성을 통해 JavaScript는 크로스 플랫폼 모바일 애플리케이션을 개발하는 데 사용됩니다. 3) 전자 프레임 워크를 사용하면 JavaScript가 데스크탑 애플리케이션을 구축 할 수 있습니다. 4) node.js는 JavaScript가 서버 측에서 실행되도록하고 동시 요청이 높은 높은 요청을 지원합니다.

Python은 데이터 과학 및 자동화에 더 적합한 반면 JavaScript는 프론트 엔드 및 풀 스택 개발에 더 적합합니다. 1. Python은 데이터 처리 및 모델링을 위해 Numpy 및 Pandas와 같은 라이브러리를 사용하여 데이터 과학 및 기계 학습에서 잘 수행됩니다. 2. 파이썬은 간결하고 자동화 및 스크립팅이 효율적입니다. 3. JavaScript는 프론트 엔드 개발에 없어서는 안될 것이며 동적 웹 페이지 및 단일 페이지 응용 프로그램을 구축하는 데 사용됩니다. 4. JavaScript는 Node.js를 통해 백엔드 개발에 역할을하며 전체 스택 개발을 지원합니다.

C와 C는 주로 통역사와 JIT 컴파일러를 구현하는 데 사용되는 JavaScript 엔진에서 중요한 역할을합니다. 1) C는 JavaScript 소스 코드를 구문 분석하고 추상 구문 트리를 생성하는 데 사용됩니다. 2) C는 바이트 코드 생성 및 실행을 담당합니다. 3) C는 JIT 컴파일러를 구현하고 런타임에 핫스팟 코드를 최적화하고 컴파일하며 JavaScript의 실행 효율을 크게 향상시킵니다.

실제 세계에서 JavaScript의 응용 프로그램에는 프론트 엔드 및 백엔드 개발이 포함됩니다. 1) DOM 운영 및 이벤트 처리와 관련된 TODO 목록 응용 프로그램을 구축하여 프론트 엔드 애플리케이션을 표시합니다. 2) Node.js를 통해 RESTFULAPI를 구축하고 Express를 통해 백엔드 응용 프로그램을 시연하십시오.

웹 개발에서 JavaScript의 주요 용도에는 클라이언트 상호 작용, 양식 검증 및 비동기 통신이 포함됩니다. 1) DOM 운영을 통한 동적 컨텐츠 업데이트 및 사용자 상호 작용; 2) 사용자가 사용자 경험을 향상시키기 위해 데이터를 제출하기 전에 클라이언트 확인이 수행됩니다. 3) 서버와의 진실한 통신은 Ajax 기술을 통해 달성됩니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

Dreamweaver Mac版
시각적 웹 개발 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

드림위버 CS6
시각적 웹 개발 도구
