在本章中,你将学会如何处理可以复用的代码块。
在定价方案视图中,可以看到3个定价方案的样式还有代码是极其相似的。
和设计的逻辑一样,代码的逻辑也是是“复制”第一个定价方案的视图的代码,然后再修改颜色、字体、或者加多一些文字。
但他们的主体结构是一样的。
那么我们是不是可以只需要写一次代码,然后把文字什么的再复用重定义。
这样可以大大减少代码量,且代码阅读起来更加清晰,做到“优雅写代码”的目的。
//定价方案子视图 struct pricingView: View { var body: some View { HStack { // 连续包月 ZStack { VStack { Text("连续包月") .fontWeight(.bold) .font(.system(size: 17)) .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255)) Text("¥18") .fontWeight(.bold) .font(.system(size: 30)) .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255)) } .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90) .padding(20) .background(Color("faf7f3")) .overlay(RoundedRectangle(cornerRadius: 6) .stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2)) // 首月特惠 Text("首月特惠") .font(.system(size: 14)) .fontWeight(.bold) .foregroundColor(.white) .padding(5) .background(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255)) .cornerRadius(4) .offset(x: 0, y: -65) } // 1个月 VStack { Text("1个月") .fontWeight(.bold) .font(.system(size: 17)) .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255)) Text("¥30") .fontWeight(.bold) .font(.system(size: 30)) .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255)) } .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90) .padding(20) .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) .cornerRadius(10) // 12个月 VStack { Text("12个月") .fontWeight(.bold) .font(.system(size: 17)) .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255) Text("¥228") .fontWeight(.bold) .font(.system(size: 30)) .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255)) Text("¥19.00/月") .fontWeight(.bold) .font(.system(size: 17)) .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255)) } .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90) .padding(20) .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) .cornerRadius(10) } // HStack结束位置 .padding(.horizontal) } } 复制代码
说干就干!
首先分析下代码的相同点。
Text()下,设置字重、字体、字体颜色,在整个VStack包裹下,设置尺寸、边距、背景颜色、边框圆角。
我们发现,除了定价方案的标题不同(连续包月、1个月、12个月)、不同定价方案的价格不同(¥18、¥30、¥228)、背景颜色不同,其他都一样。
既然这些都可以复用,那么我们可以将可以复用的参数脱离出来。
先定义一个变量,再在代码中设定不同的变量值,就可以达到全部复用的效果。
先定一个标准的定价方案,定义了一个title变量,它是字符串类型,定义了一个价格变量,也是字符串类型,定一个一个背景颜色,它是颜色类型。
然后将定义的变量换到下面的代码中。
//定价方案 struct pricingView: View { //定义变量 var title: String var price: String var bgColor: Color var body: some View { VStack { Text(title) //定义的titie .fontWeight(.bold) .font(.system(size: 17)) .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255)) Text(price) //定义的price .fontWeight(.bold) .font(.system(size: 30)) .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255)) } .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90) .padding(20) .background(bgColor) //定义的背景颜色 } 复制代码
定义完变量后,我们可以看到系统报错了,不用担心。
这因为我们pricingView子视图中定义了3个变量,但在主视图引用的时候,主视图不知道这3个变量是什么值,只知道它的类型。
所以系统提醒我们需要加上具体的值。
我们可以点击“Fix”,Xcode会自动帮我们加上缺少的值。
“Fix”后,Xcode将缺少的变量补充了进来。
这时候,我们需要给变量赋予真实的值。
示例:title赋予"连续包月”,price赋予"¥18”,bgColor赋予Color("faf7f3”)。
// 定价方案 pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3"))
很好,我们已经创建好了1个定价方案了!
像UI稿一样,我们需要3个定价方案,由于我们已经拆离开可以复用的代码了,那么我们只需要在主视图复制就行了,而无需再额外复制一大段代码。
// 定价方案 //连续包月 pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3")) //1个月 pricingView(title: "1个月", price: "¥30", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) //12个月 pricingView(title: "12个月", price: "¥228", bgColor: Color(red: 244 / 255, green: 2
由于在主视图中,我们的标题和定价方案是放在一个VStack里面的,而3个定价方案需要横向分布,也就是使用HStack。
那我们只需要在主视图中将3个定价方案放在一个HStack中,这样它们就能横向排列了。
// 定价方案 HStack { //连续包月 pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3")) //1个月 pricingView(title: "1个月", price: "¥30", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) //12个月 pricingView(title: "12个月", price: "¥228", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) }
下一步,我们修订下样式,我们可以看到第一个定价方案是有圆角边框的,其他两个定价方案是有圆角的。
那么我们需要单独为第一个定价方案加圆角边框,其他两个定价方案加圆角。
// 定价方案 HStack { //连续包月 pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3”)) .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2)) //1个月 pricingView(title: "1个月", price: "¥30", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) .cornerRadius(10) //12个月 pricingView(title: "12个月", price: "¥228", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) .cornerRadius(10) }
下一步,我们看到UI稿中,第一个定价有【首月特惠】的标识,其他两个定价方案是没有的。
那么我们需要再给第一个定价方案用ZStack包裹,然后再里面添加一个【首月特惠】的标识。
//连续包月 ZStack { // 连续包月 pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3")) .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2)) // 首月特惠 Text("首月特惠") .font(.system(size: 14)) .fontWeight(.bold) .foregroundColor(.white) .padding(5) .background(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255)) .cornerRadius(4) .offset(x: 0, y: -65) }
这时候,我们会发现样式基本okay了。
但有个问题,主视图的代码好像太多了,不够优雅。
结合上一章所学的代码分组管理,我们可以把【首月特惠】单独抽离出来成为一个子视图。
鼠标移动到ZStack定价方案里的Text()视图,按住command键,点击选择Text()视图,选择Extract SubView。
在得到新的子视图后,我们依旧需要重命名。
我们把首月特惠的ExtractedView更名为specialOfferView。
鼠标定位到原来没有命名的ExtractedView位置,点击鼠标右键,选择Refactor,选择Rename。
很好!代码优雅多了!
然后,我们再给HStack加个.padding。
你以为完成了吗?并不!
我们看到第三个定价方案还有1个Text(“¥19.00/月”),而其他定价方案没有。
先思考下怎么做。
在pricingView里加一个Text()?先试试吧。
和之前一样,我们定一个perPrice变量,它是String类型。
然后在pricingView中加上Text(perPrice)的代码。
//定价方案子视图 struct pricingView: View { // 定义变量 var title: String var price: String var perPrice: String var bgColor: Color var body: some View { VStack { Text(title) .fontWeight(.bold) .font(.system(size: 17)) .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255)) Text(price) .fontWeight(.bold) .font(.system(size: 30)) .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255)) Text(perPrice) .fontWeight(.bold) .font(.system(size: 17)) .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255)) } .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90) .padding(20) .background(bgColor) } }
再回到主视图中,补充缺失的变量。
点击“Fix”,Xcode会自动补充缺失的变量。
补充缺失的变量后,根据定义好的数据类型,完成相对应的数据即可。
这样,我们就完成了整个定价方案的编程!
// 定价方案 HStack { // 连续包月 ZStack { pricingView(title: "连续包月", price: "¥18", perPrice: "", bgColor: Color("faf7f3") .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2)) // 首月特惠 specialOfferView() } // 1个月 pricingView(title: "1个月", price: "¥30", perPrice: "", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) .cornerRadius(10) // 12个月 pricingView(title: "12个月", price: "¥228", perPrice: "¥19.00/月", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255)) .cornerRadius(10) } .padding()