Rails Rails 6 基于前端的省市区乡镇四级联动选择菜单的实践

Chorder · 2021年08月07日 · 最后由 Chorder 回复于 2021年08月07日 · 699 次阅读

用到的库(前端):

yarn add jquery province-city-china

Views:

<h1>Demo#index</h1>
<p>Find me in app/views/demo/index.html.erb</p>

<%= form_with url: root_path, method: :get do |form| %>

<%= form.label :省份 %>
<%= form.select(:province,[],
    {include_blank:"请选择",selected:params[:province]},
    { class:"pcat_select provinces", :required=>false}) %>

<%= form.label :城市 %>
<%= form.select(:city,[],
    {include_blank:"请选择",selected:params[:city]},
    { class:"pcat_select cities", :required=>false}) %>

<%= form.label :区县 %> 
<%= form.select(:area,[],
    {include_blank:"请选择",selected:params[:area]},
    { class:"pcat_select areas", :required=>false}) %>

<%= form.label :乡镇 %>
<%= form.select(:town,[],
    {include_blank:"请选择",selected:params[:town]},
    { class:"pcat_select towns", :required=>false}) %>

<%= form.submit "提交" %>

<% end %>

Javascript


import $ from "jquery"

const provinces = require('province-city-china/dist/province.json');
const cities = require('province-city-china/dist/city.json');
const areas = require('province-city-china/dist/area.json');
const towns = require('province-city-china/dist/town.json');


$(document).on("turbolinks:load",function(){
    // 填充省份
    provinces.map(x => x.name).forEach( (value,index) => {
        $(".pcat_select.provinces").append( $("<option></option>").text(value).attr("value",value) );
    });

    //城市联动
    $(".pcat_select.provinces").on('change',function(){
        $(".pcat_select.cities,.pcat_select.areas,.pcat_select.towns").html('<option value=""></option>');

        if ( $(this).val() != ""){
            var province = provinces.find( x => x.name == $(this).val() );
            var child_cities = cities.filter(x => (x.province == province.province) ).map( x => x.name );
            child_cities.forEach( (value,index) => {
                $(".pcat_select.cities").append( $("<option></option>").text(value).attr("value",value) );
            });
        }

    });

    // 区县联动
    $(".pcat_select.cities").on('change',function(){
        $(".pcat_select.areas,.pcat_select.towns").html('<option value=""></option>');

        if ( $(this).val() != ""){
            var city = cities.find( x => x.name == $(this).val() );
            var child_areas = areas.filter(x => ( x.province == city.province && x.city == city.city) ).map( x => x.name );
            child_areas.forEach( (value,index) => {
                $(".pcat_select.areas").append( $("<option></option>").text(value).attr("value",value) );
            });
        }

    });

    // 乡镇联动
    $(".pcat_select.areas").on('change',function(){
        $(".pcat_select.towns").html('<option value=""></option>');
        if ( $(this).val() != ""){
            var area = areas.find( x => x.name == $(this).val() );
            var child_towns = towns.filter(x => (x.province == area.province && x.city == area.city && x.area == area.area) ).map( x => x.name );
            child_towns.forEach( (value,index) => {
                $(".pcat_select.towns").append( $("<option></option>").text(value).attr("value",value) );
            });
        }
    });


});

自我感觉不是很优雅,先分享作为一个记录吧,希望以后有机会变 DRY。

mingyuan0715 回复

研究了一下你的方案,学到了一些新的东西,感谢!

我将数据库放在前端是想减少一次 HTTP 通信和后端计算,与从后端来查询响应相比算各有利弊吧。

另外在研究的时候看到了你正在做的 work.design 项目,里面有大量不错的实践,像是个宝藏,正在 (偷) 消 (学) 化中。😎

需要 登录 后方可回复, 如果你还没有账号请 注册新账号