项目代码地址:https://coding.net/u/kamionayuki/p/tools/git 自己想写一个实现页面级联的功能,思路如下:
先获得城市的源数据,然后改成yaml的格式。一般来说,都是1个城市名称对应一个代码,代码可以是邮政编码,也可以是其它的,但肯定是一级城市与下级地区有关联。在服务器启动的时候,初始化一个常量,存放该数据。例如:
city.yaml
---
"北京(直辖市)": "101010000"
"北京": "101010100"
"海淀": "101010200"
"朝阳": "101010300"
"顺义": "101010400"
"怀柔": "101010500"
"通州": "101010600"
"昌平": "101010700"
"延庆": "101010800"
"丰台": "101010900"
"石景山": "101011000"
"大兴": "101011100"
"房山": "101011200"
"密云": "101011300"
"门头沟": "101011400"
"平谷": "101011500"
"八达岭": "101011600"
"佛爷顶": "101011700"
"汤河口": "101011800"
"密云上甸子": "101011900"
"斋堂": "101012000"
"霞云岭": "101012100"
.....
config/initializers,新增一个rb
require 'yaml'
require 'open-uri'
require 'uri'
HAN_NAME = YAML.load(File.read(File.expand_path('../../../lib/genname.txt', __FILE__)))
CITY_DATA = YAML.load(File.read(File.expand_path('../../../lib/city.yaml', __FILE__)))
根据源数据把一级城市和二级城市的数据分开,并关联起来。
helpers/application_helper.rb
def get_provinces
provinces = CITY_DATA.select {|k,v| v[-4..-1] == "0000"}.to_a
provinces.unshift(["--省份--", 0])
end
def get_cities(province_code)
cities = [["--城市--", 0]]
return cities if province_code == 0
if ["101010000", "101020000", "101030000", "101010000"].include?(province_code)
province_code[-3] = "1"
cities = CITY_DATA.select {|k,v| v == province_code}.to_a
else
cities = CITY_DATA.select {|k,v| v[3,2] == province_code[3,2] && v[-2..-1] == "01" }.to_a
end
cities.unshift(["--城市--", 0])
end
def get_area(province_code, city_code)
areas = [["--地区--", 0]]
return cities if city_code == 0
if ["101010000", "101020000", "101030000", "101010000"].include?(province_code)
areas = CITY_DATA.select {|k,v| v[0..4] == city_code[0..4] && !["100", "000"].include?(v[-3..-1]) }.to_a
else
areas = CITY_DATA.select {|k,v| v[0..-3] == city_code[0..-3] && !["00", "01"].include?(v[-2..-1])}.to_a
end
areas.unshift(["--地区--", 0])
end
在views中填写如下的代码:
<%= form_tag({controller: "tools", action: "get_weatherinfo"}, method: "get", remote: true) do %>
<div class="city-group">
<%= select_tag :province, options_for_select(get_provinces,0), class: "province-select" %>
<%= render('tools_form/cities', cities: [["--城市--", 0]]) %>
<%= render('tools_form/areas', areas: [["--地区--", 0]]) %>
</div>
<%= button_to "查询天气" %>
<% end -%>
因为cities 和 areas是一个变值,会通过controller来获得,所以单独拿出来进行传值
tools_form/_cities.html.erb 和 tools_form/_areas.html.erb
<%= select_tag :city, options_for_select(cities, 0), class: "city-select" %>
# tools_form/_areas.html.erb
<%= select_tag :area, options_for_select(areas, 0), class: "area-select" %>
通过jquery来监听下拉菜单中值的变化,一旦有变化,则调用controller中的方法来获得对应的城市和地区
javascripts/tools.js。其中用$.post来传递一个url和一个值
如果province变化,则调用"/tools/get_cities_result",同时传递一个params[:province]的参数。
这样,get_cities_results就能使用该参数,从而获得对应的city,然后通过对应的js.erb文件来渲染当前页面
$('#province').change(function(){
var province = $(this).children('option:selected').val();//这就是selected的值
$.post("/tools/get_cities_result",
{
province: province
});
});
$('#city').change(function(){
var province = $(this).prev().children('option:selected').val();
var city = $(this).children('option:selected').val();//这就是selected的值
$.post("/tools/get_areas_result",
{
province: province,
city: city
});
});
controller中#因为要用到helper中的方法,所在以controllers/application_controller.rb中增加
include ApplicationHelper
tools_controller中,通过下面的方法来获得对应的城市和区域的值,然后用@cities和@areas来传递
def get_cities_result
@cities = get_cities(params[:province])
end
def get_areas_result
@areas = get_area(params[:province], params[:city])
end
因为是通过jquery.post方法来传递调用上面的方法的,所以对应的是js.erb文件,用来改变页面中城市和区域下拉框的值
tools/get_cities_result.js.erb
$('#city').html("<%=j render('tools_form/cities', cities: @cities) %>");
$('#area').html("<%=j render('tools_form/areas', areas: [["--地区--", 0]]) %>");
#tools/get_areas_result.js.erb
$('#area').html("<%=j render('tools_form/areas', areas: @areas) %>");
routes中
namespace :tools do
get 'index'
get 'rand_en_name'
get 'rand_han_name'
get 'rand_password'
get 'timestamp_to_time'
get 'time_to_timestamp'
get 'han_number_transfer'
get 'get_weatherinfo'
get 'export'
post 'get_cities_result'
post 'get_areas_result'
end
这样就实现了级联了。但不是纯前端的,网络差的时候,反应会慢一点。但这样就可以实现不仅仅是城市的级联了。类似于某某县某某高中某某年级某某班的级联都可以实现了。