Flex的数据绑定方式一览

本文介绍了Flex中的多种数据绑定方式,包括从XML文件加载数据、处理HTTP请求返回的数据、使用ArrayCollection类以及绑定对象属性等内容。此外还介绍了Flex中的一些实用技巧,如排序、游标操作等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       学Flex2个多星期了,也没觉得有什么难的地方,可能是老外写的那本<<Flex权威指南>>比较浅显易懂吧,有时不得不佩服老外做事的认真劲和耐心,图文对照,很容易理解。现在数据绑定部分看完了,总结一下书中提到的数据绑定方式。

      1.数据存放在XML文件中,XML文件存在在工程内,可以直接引用,方式如下:

         <mx:Model id="xxx" source="yyy">yyy为XML文件路径+文件名。然后在事件中进行绑定,比如:

         <mx:Button click="do(xxx)"/> xxx为上面的id,do(xxx)为AS方法名,通过该方法将数据绑定到控件上。

      2.数据来自事件event,target事件源,比如被点击的某个控件; type事件类型,比如Click,mouseover等等。主要谈谈比较特殊的mx.rpc.events.ResultEvent,这个事件封装了HTTP请求的返回数据。

 <mx:HTTPService id="catRPC" url="http://www.flexgrocer.com/category.xml" result="catHandler(event)" resultFormat="e4x"/>

在catHandler(event)中,可以直接从event中获取数据源用于绑定。具体实现方法如下:

         1)在Script块创建1个变量aaa,并加上[Bindable]标签,表明该数据可用于绑定。

         2)在catHandler(event)函数中,将event封装的请求返回数据赋值给aaa;

         3)在程序里可以就可以将aaa用于数据绑定了,e4x就是ActionScript原生的XML对象。

      3.用于数据绑定的特殊类ArrayCollection,该类在数据发生变化时,视觉显示也会随着更新。

      4.将对象的某个属性绑定到List等控件时,除了要指定绑定的数据源,还要指定绑定的对象属性。

         <mx:List rowCount="4" dataProvider="{units}" labelField="unitName"/>    

          dataProvider数据源 labelField绑定的属性名

       5.@Embed标签用来决定是否把引用的文件编译进FLASH文件。

       6.for each(var p:XML in event.result..product){},2个点表示后代存取器,表示遍历出result中所有的product节点。

       7.{}用于数据绑定,@取绑定对象的属性。

       <mx:Button id="Add" label="Add to Cart" click="addToCart(inventory.getItemAt(0) as Product)"/>

        as表示希望编译器忽略类型差别把取出来的元素当Product类处理。

       8.排序

          var prodSort:Sort = new Sort();

          var sortField:SortField = new SortField("product");  //对product进行排序

          prodSort.fields = new Array(sortField);

          aItems.sort = prodSort;

          aItems.refresh();

        9.IViewCursor接口,调用ArrayCollection的createCursor()方法可以获得cursor,然后可以ORACLE操作游标一样操作ArrayCollection。       

          findFirst(),findAny(),moveNext(); remove();

        10.命名空间namespace,用来标示将引用的资源的路径。

        11.TitleWindow适合用来做弹出窗口。mx.managers.PopUpManager类可以创建弹出窗口。

         ConfirmScreen win = ConfirmScreen(PopUpManager.createPopUp(this,ConfirmScreen,true));this指当前控件,第2个是弹出的窗体类型,第3个参数表示是否是模式窗口。

        12.HorizontalList沿水平方向显示项目,TileList动态创建大小相等的行列显示项目。

             labelField绑定的字段名称 labelFunction调用函数绑定(可以将数据预处理了显示)。itemRender属性可以用来显示图片,itemRender属性指向某个MXML文件。

         13.Repeater 相当于for循环对数据集进行遍历。

业务一览画面:<template> <el-table :data="tableData" style="width: 100%" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" /> <el-table-column label="产品名称" width="220"> <template #default="scope"> <div class="product-name-wrapper"> <el-link type="primary" :underline="false" @click="goToProductDetail(scope.row.id)"> <span>{{ scope.row.name }}</span> </el-link> </div> </template> </el-table-column> <el-table-column property="categoryName" label="产品分类" width="120" /> <el-table-column property="price" label="产品单价" width="120" /> <el-table-column property="createAt" label="生产日期" width="250" /> <el-table-column property="price" label="单价" width="120" /> <el-table-column property="stock" label="库存" width="120" /> <el-table-column label="购买数量" width="180"> <template #default="scope"> <div> <el-input-number v-model="scope.row.number" :min="0" :max="scope.row.stock" size="small" controls-position="right" /> </div> </template> </el-table-column> <el-table-column label="合计" width="120"> <template #default="scope"> ¥{{ (scope.row.price * scope.row.number) }} </template> </el-table-column> <el-table-column label="操作" width="180"> <template #default="scope"> <el-button size="small" @click="handleEdit(scope.$index, scope.row)"> 编辑 </el-button> <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)"> 删除 </el-button> </template> </el-table-column> </el-table> <div class="footer"> <el-button type="primary" round @click="addToCart">加入购物车</el-button> </div> <div class="summary"> <span>总金额:</span> <span>¥{{ (totalAmount) }}</span> </div> </template> <script setup> const router = useRouter(); const user = "aaa" import productApi from '@/api/products' import { ref, computed } from 'vue'; import { ElMessageBox, ElMessage } from 'element-plus' const tableData = ref([]); const goToProductDetail = (productId) => { router.push({ path: `/home/test/${productId}`, query: { type: 'view' } }) } // 编辑详情页 const handleEdit = (index, row) => { router.push({ path: `/home/test/${row.id}`, // 添加查询参数表示编辑模式 query: { type: 'edit' } }) } // 删除操作 const handleDelete = (index, row) => { ElMessageBox.confirm( '确定要删除该商品吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } ).then(() => { // 调用 API 删除商品 productApi.delete(row.id).then(res => { // 删除成功后从前端移除 tableData.value.splice(index, 1) ElMessage.success('删除成功') }).catch(err => { console.error('删除失败:', err) ElMessage.error('删除失败,请重试') }) }).catch(() => { // 用户点击取消 ElMessage.info('已取消删除') }) } // 获取商品数据 function getProduct() { productApi.getAll(user).then(res => { tableData.value = res.data.map(item => ({ ...item, number: item.number || 0, })); }); } // 创建一个响应式数组,用于存储选中的项 const allcheckbox = ref([]) function handleSelectionChange(selection) { // 当选择变化时更新存储的选中项 allcheckbox.value = selection } // 计算总金额 const totalAmount = computed(() => { return allcheckbox.value.reduce((sum, row) => { const price = parseFloat(row.price) || 0; const number = parseInt(row.number) || 0; return sum + (price * number); }, 0); }); // 加入购物车 const addToCart = () => { const selectedItems = allcheckbox.value; if (!selectedItems.length) { ElMessage.warning('请先选择要加入购物车的商品'); return; } selectedItems.forEach(item => { const payload = { name: item.name, price: item.price, category: item.category, quantity: item.number, user: user }; productApi.addCarItem(payload) .then(res => { ElMessage.success(`${item.name} 加入购物车成功`); }) .catch(error => { console.error(`添加 ${item.name} 到购物车失败`, error); ElMessage.error(`添加 ${item.name} 失败`); }); }); getProduct(); // 刷新商品列表 allcheckbox.value = []; }; onMounted(() => { getProduct(); }); </script> <style scoped> .summary { float: right; margin-top: 55px; margin-right: 50px; } .footer { float: right; margin-top: 50px; margin-right: 280px; } </style> 商品详情画面:<template> <el-form ref="ruleFormRef" style="margin-top: 20px;max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto" :disabled="pageMode === 'view'"> <el-form-item label="产品名称:" prop="name"> <el-input v-model="ruleForm.name" /> </el-form-item> <el-form-item label="产品描述:" prop="description"> <el-input v-model="ruleForm.description" type="textarea"/> </el-form-item> <el-form-item label="产品分类:" prop="category" style="width: 50%;"> <el-select v-model="ruleForm.category" placeholder="请选择分类"> <el-option v-for="item in categorys" :label="item.name" :value="item.id" :key="item.id" /> </el-select> </el-form-item> <el-form-item label="产品单价:" prop="price"> <el-input v-model.number="ruleForm.price" type="number" style="width: 240px" /> </el-form-item> <el-form-item label="产品库存:" prop="stock"> <el-input v-model.number="ruleForm.stock" type="number" style="width: 240px" /> </el-form-item> <el-form-item label="生产厂家:" prop="manufacturer"> <el-input v-model="ruleForm.manufacturer" /> </el-form-item> <el-form-item label="产地:" required> <el-col :span="12"> <el-form-item prop="originProvince"> <el-select v-model="ruleForm.originProvince" placeholder="省" style="flex: 1; margin-right: 10px"> <el-option v-for="item in originProvinces" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item prop="originCity"> <el-select v-model="ruleForm.originCity" placeholder="市" style="flex: 1 " :disabled="!ruleForm.originProvince"> <el-option v-for="item in originCitys" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> </el-form-item> <el-form-item label="发货地:" required> <el-col :span="12"> <el-form-item prop="shippingProvince"> <el-select v-model="ruleForm.shippingProvince" placeholder="省" style="flex: 1; margin-right: 10px"> <el-option v-for="item in originProvinces" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item prop="shippingCity"> <el-select v-model="ruleForm.shippingCity" placeholder="市" style="flex: 1" :disabled="!ruleForm.shippingProvince"> <el-option v-for="item in shippingCities" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> </el-form-item> <el-form-item label="生产日期" required> <el-col :span="11"> <el-form-item prop="createAt"> <el-date-picker v-model="ruleForm.createAt" type="date" aria-label="Pick a date" placeholder="Pick a date" style="width: 100%" /> </el-form-item> </el-col> </el-form-item> <el-form-item> <!-- 登录按钮:仅在默认模式下显示 --> <el-button v-if="pageMode === 'default'" style="margin-left: 18px;" type="primary" @click="submitForm(ruleFormRef, ruleForm)"> 登录 </el-button> <!-- 更新按钮:仅在编辑模式下显示 --> <el-button v-if="pageMode === 'edit'" style="margin-left: 30px;" type="primary" @click="updateForm(ruleFormRef)"> 更新 </el-button> <!-- 重置按钮:在编辑或默认模式下都显示 --> <el-button v-if="pageMode === 'edit' || pageMode === 'default'" style="margin-left: 30px;" type="primary" @click="resetForm(ruleFormRef)"> 重置 </el-button> </el-form-item> </el-form> </template> <script setup> import { ref, reactive, onMounted } from 'vue'; import productApi from '@/api/products' import placeApi from '@/api/place' import { useRouter } from 'vue-router' import { ElLoading, ElMessage } from 'element-plus' const pageMode = ref('') // 可选值: 'view', 'edit', 'default' const router = useRouter(); const ruleFormRef = ref() const categorys = ref([])// 产品分类 const originProvinces = ref([]) // 省份数据 const originCitys = ref([]) // 城市数据 const shippingCities = ref([]) // 发货地城市数据 const ruleForm = reactive({ name: '', description: '', category: '', price: '', stock: '', manufacturer: '', originProvince: '', originCity: '', shippingProvince: '', shippingCity: '', createAt: '', user: 'aaa', delivery: false, type: [], }) const rules = reactive({ name: [ { required: true, message: '请输入产品名称', trigger: 'blur' }, { max: 10, message: '长度超过10位', trigger: 'blur' }, ], description: [ { required: true, message: '请输入产品描述', trigger: 'blur' }, { max: 200, message: '长度超过200位', trigger: 'blur' }, ], category: [ { required: true, message: '请选择产品分类', trigger: 'change', }, ], price: [ { required: true, message: '请输入产品单价', trigger: ['blur', 'change'] }, { validator: (rule, value, callback) => { if (value === null || value === '') { callback(new Error('请输入产品单价')) } else if (value <= 0) { callback(new Error('单价必须大于 0')) } else if (value > 10000) { callback(new Error('单价不能大于 10000')) } else { callback() } }, trigger: ['blur', 'change'] } ], stock: [ { required: true, message: '请输入产品库存', trigger: ['blur', 'change'] }, { validator: (rule, value, callback) => { if (value === null || value === '') { callback(new Error('请输入商品单价')) } else if (value <= 0) { callback(new Error('单价必须大于 0')) } else if (value > 10000) { callback(new Error('单价不能大于 10000')) } else { callback() } }, trigger: ['blur', 'change'] } ], manufacturer: [ { required: true, message: '请输入生产厂家', trigger: 'blur' }, ], originProvince: { validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择产地省份')) } else { callback() } }, trigger: 'change' }, originCity:{ validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择产地城市')) } else { callback() } }, trigger: 'change' }, shippingProvince: { validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择发货省份')) } else { callback() } }, trigger: 'change' }, shippingCity:{ validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择发货城市')) } else { callback() } }, trigger: 'change' }, createAt: [ { type: 'date', required: true, message: '请输入日期', trigger: 'change', }, ], }) // 重置表单操作 const resetForm = (formEl) => { if (!formEl) return formEl.resetFields() } //产品分类 function getCategory() { productApi.getCategory().then(res => { categorys.value = res.data; }) } // 获取商品详情 function getProductDetail(productId) { productApi.getById(productId).then(res => { const data = res.data // 先赋值整个对象 Object.assign(ruleForm, data) }).catch(error => { console.error('获取商品详情失败:', error); }); } // 获取省份 function getProvinces() { placeApi.getProvince().then(res => { originProvinces.value = res.data }).catch(error => { console.error('获取省份失败:', error) }) } // 监听产地省份变化,加载城市 watch( () => ruleForm.originProvince, (newVal) => { if (newVal) { placeApi.getCity(newVal).then(res => { originCitys.value = res.data }).catch(() => { originCitys.value = [] }) } else { // 如果省份为空,则清空城市列表和当前选中的城市字段 originCitys.value = [] ruleForm.originCity = '' } } ) // 监听发货地省份变化,加载城市 watch( () => ruleForm.shippingProvince, (newVal) => { if (newVal) { placeApi.getCity(newVal).then(res => { shippingCities.value = res.data }).catch(() => { shippingCities.value = [] }) } else { // 如果省份为空,则清空城市列表和当前选中的城市字段 shippingCities.value = [] ruleForm.shippingCity = '' } } ) // 更新操作 const updateForm = async (formEl) => { if (!formEl) return const loading = ElLoading.service({ fullscreen: true }) await formEl.validate((valid, fields) => { if (valid) { console.log('开始提交...') // 调用 API 更新商品信息 productApi.update(ruleForm).then(res => { ElMessage.success('更新成功') router.push('/home/test1') // 可选跳转回列表页 }).catch(error => { console.error('更新失败:', error) ElMessage.error('更新失败,请重试') }).finally(() => { loading.close() }) } else { console.log('表单验证失败:', fields) ElMessage.error('请检查输入内容') loading.close() return false } }) } // 登录操作 const submitForm = async (formEl, ruleForm) => { if (!formEl) return await formEl.validate((valid, fields) => { if (valid) { console.log('开始提交商品...') const loading = ElLoading.service({ fullscreen: true }) productApi.addProduct(ruleForm).then(res => { ElMessage.success('登录成功') router.push('/home/test1') }).catch(error => { console.error('登录失败:', error) ElMessage.error('登录失败,请重试') }).finally(() => { loading.close() }) } else { console.log('表单验证失败:', fields) ElMessage.error('请检查输入内容') loading.close() return false } }) } onMounted(() => { getCategory() getProvinces() // 获取当前路由信息 const route = router.currentRoute.value // 判断页面是查看、编辑还是新增模式 const type = route.query.type const productId = route.params.id || route.query.id if (type === 'view') { pageMode.value = 'view' // 查看模式:不显示按钮 } else if (type === 'edit') { pageMode.value = 'edit' // 编辑模式:显示“更新”、“重置” } else { pageMode.value = 'default' // 默认模式:显示“登录”、“重置” } // 如果存在商品 ID,则调用接口获取商品详情并填充表单 if (productId) { getProductDetail(productId) } }) </script> <style> .location-selectors { display: flex; justify-content: space-between; width: 100%; } </style> 购物车画面:<template> <el-table :data="tableData" style="width: 100%"> <el-table-column property="name" label="产品名称" width="220"/> <el-table-column property="categoryName" label="产品分类" width="120" /> <el-table-column property="price" label="产品单价" width="120" /> <el-table-column property="createAt" label="生产日期" width="250" /> <el-table-column property="price" label="单价" width="120" /> <el-table-column property="quantity" label="购买数量" width="180"> <template #default="scope"> <div> <el-input-number v-model="scope.row.number" :min="0" :max="scope.row.stock" size="small" controls-position="right" /> </div> </template> </el-table-column> <el-table-column label="合计" width="120"> <template #default="scope"> ¥{{ (scope.row.price * scope.row.number) }} </template> </el-table-column> <el-table-column label="操作" width="180"> <template #default="scope"> <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)"> 删除 </el-button> </template> </el-table-column> </el-table> <div class="footer"> <el-button type="primary" round>结算</el-button> </div> <div class="summary"> <span>总金额:</span> <span>¥{{ (totalAmount) }}</span> </div> </template> <script setup> const router = useRouter(); const user = "aaa" import productApi from '@/api/products' import { ref, computed } from 'vue'; import { ElMessageBox, ElMessage } from 'element-plus' const tableData = ref([]); // 删除操作 const handleDelete = (index, row) => { ElMessageBox.confirm( '确定要删除该商品吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } ).then(() => { // 调用 API 删除商品 productApi.deleteCar(row.id).then(res => { // 删除成功后从前端移除 tableData.value.splice(index, 1) ElMessage.success('删除成功') }).catch(err => { console.error('删除失败:', err) ElMessage.error('删除失败,请重试') }) }).catch(() => { // 用户点击取消 ElMessage.info('已取消删除') }) } function getProduct() { productApi.getCartAll(user).then(res => { tableData.value = res.data.map(item => ({ ...item, number: item.quantity || 0 })); }); } // 计算总金额 const totalAmount = computed(() => { return tableData.value.reduce((sum, row) => { const price = parseFloat(row.price) || 0; const number = parseInt(row.number) || 0; return sum + (price * number); }, 0); }); onMounted(() => { getProduct(); }); </script> <style scoped> .summary { float: right; margin-top: 55px; margin-right: 50px; } .footer { float: right; margin-top: 50px; margin-right: 510px; } </style> 现在我想将商品详情画面拆成像之前的4层组件结构,而购物车和商品一览画面保持不变,只将商品详情画面的form表单拆成自定义组件功能保持不变
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值