如何遍历和渲染表示嵌套树的实例化路径数组中的嵌套HTML?

时间:2019-07-12 12:48:33

标签: javascript reactjs tree nested jsx

我有一个数组,该数组在AJAX调用后收到了前端React组件。该数组不过是从后端发送的带注释的列表,该列表表示Django-Treebeard模型数据。带注释的列表是物化路径树,它以平面数组的形式构造嵌套树的所有节点。

以下是前端反应中可用的确切数据:

const data = [
  {
    info: { close: [], open: true, level: 1 },
    spot: {
      id: 2,
      path: "00020002",
      depth: 2,
      numchild: 0,
      landmark_name: "Metrolink Trafford Depot",
      distance: "700.00",
      unit: "m",
      child: 0
    }
  },
  {
    info: { close: [], open: false, level: 1 },
    spot: {
      id: 3,
      path: "00020003",
      depth: 2,
      numchild: 0,
      landmark_name: "Bus Stand",
      distance: "300.00",
      unit: "m",
      child: 0
    }
  },
  {
    info: { close: [], open: false, level: 1 },
    spot: {
      id: 4,
      path: "00020005",
      depth: 2,
      numchild: 2,
      landmark_name: "Restaurants and Bars",
      distance: null,
      unit: null,
      child: 1
    }
  },
  {
    info: { close: [], open: true, level: 2 },
    spot: {
      id: 5,
      path: "000200050001",
      depth: 3,
      numchild: 2,
      landmark_name: "Trafford Bar",
      distance: 650.00,
      unit: "m",
      child: 1
    }
  },
  {
    info: { close: ["0"], open: false, level: 2 },
    spot: {
      id: 6,
      path: "000200050003",
      depth: 3,
      numchild: 0,
      landmark_name: "Café Hardrock",
      distance: "1.50 ",
      unit: "km",
      child: 0
    }
  },
  {
    info: { close: [], open: false, level: 1 },
    spot: {
      id: 8,
      path: "00020008",
      depth: 2,
      numchild: 1,
      landmark_name: "Hospital",
      distance: null,
      unit: null,
      child: 1
    }
  },
  {
    info: { close: ["0", "1", "2"], open: true, level: 2 },
    spot: {
      id: 14,
      path: "000200080001",
      depth: 3,
      numchild: 0,
      landmark_name: "Seymour Grove Health Centre",
      distance: "320.00",
      unit: "m",
      child: 0
    }
  }
];

后端的实际数据树是:

Root
|_ Metrolink Trafford Depot: 700m
|_Bus Stand: 300 
|_Restaurant and Bars:
  |_Trafford Bar : 650m
  |_ Café Hardrock: 1.5km
|_ Hospital:
  |_ Seymour Grove Health Centre: 320m

我想创建表示上面层次结构的嵌套div结构,如下所示:

<div>
    <h3> MetroLink Trafford Depot :</h3>
    <p> 700m </p>
</div>
<div>
    <h3> Bus Stand:</h3>
    <p>300m </p>
</div>
<div>
    <h3> Restaurants and Bars:</h3>
        <div>
            <h4> Trafford Bar:</h4>
            <p> 650m</p>
        </div>
        <div>
            <h4> Café Hardrock:</h4>
            <p> 1.5km</p>
        </div>
</div>
<div>
    <h3> Hospital:</h3>
        <div> 
            <h4> Seymour Grove Health Centre:</h4>
            <p>320m</p>
        </div>
</div>

我尝试过递归,但失败了。甚至没有达到我的预期。 我尝试搜索第三方解决方案,但它们需要完全不同的数据结构。我不想更改后端的数据结构。我刚经历过的另一个地狱。另外,我认为物化路径树更适合后端效率。

如何编写React组件以根据给定数据生成以上HTML结构?

1 个答案:

答案 0 :(得分:1)

您可以首先使用@objc func appEnteredBackgound() { if let tracks = player?.currentItem?.tracks { for track in tracks { if (track.assetTrack?.hasMediaCharacteristic(AVMediaCharacteristic.visual))! { track.isEnabled = false } } } } @objc func appEnteredForeground() { if let tracks = player?.currentItem?.tracks { for track in tracks { if (track.assetTrack?.hasMediaCharacteristic(AVMediaCharacteristic.visual))! { track.isEnabled = true } } } } 属性(将其拆分为4个字符的块)从中创建嵌套的对象结构。一旦有了,就可以使用递归来创建HTML元素:

    public class MainActivity extends AppCompatActivity {
    private static Button button, butto2,reset_bu, auto;
    private static ImageView imageView;
    private static TextView textView;
    private int i=0;
    private Handler handler = new Handler();
    // image resource
    int[] images = {R.drawable.im_1, R.drawable.im_2, R.drawable.im_3,  
            R.drawable.im_24, R.drawable.im_25, R.drawable.im_26, 
                R.drawable.im_27, R.drawable.im_28, R.drawable.im_29, 
                R.drawable.im_30, R.drawable.im_31, R.drawable.im_32,
            R.drawable.im_33, R.drawable.im_34, R.drawable.im_35, 
             R.drawable.im_36, R.drawable.im_37, R.drawable.im_38, 
                R.drawable.im_39, R.drawable.im_40, R.drawable.im_41,
            R.drawable.im_42, R.drawable.im_43, R.drawable.im_44, 
            R.drawable.im_45,};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        butto2 = (Button) findViewById(R.id.button2);
        reset_bu = (Button) findViewById(R.id.reset_bu);
        final TextView textView = (TextView) findViewById(R.id.textView);
       // auto = (Button) findViewById(R.id.auto);
      //  imageView = (ImageView) findViewById(R.id.imageView);

        addListenerOnButton();
        setInitialImage();
        addback();
        reset();

    }
    public void addListenerOnButton () {
    button.setOnClickListener(new OnClickListener() {
    @Override public void onClick(View v) {
      if (i < images.length -1){
       i++;
       i = i % images.length;
       setCurrentImage();

                       }
    } });
    }
    private void setInitialImage() {
        setCurrentImage();
    }
    private void setCurrentImage() {
        final ImageView imageView = (ImageView) findViewById(R.id.imageView);
        imageView.setImageResource(images[i]);
   final TextView textView=(TextView)findViewById(R.id.textView);
   final HashMap<Integer, Integer> map = new HashMap<>();
                    map.put(R.drawable.im_1, R.string.busort);
                    map.put(R.drawable.im_2, R.string.busort2);
                    int busort = map.get(R.drawable.im_1);
                    int busort2 = map.get(R.drawable.im_2);
                    int busort3 = map.get(R.drawable.im_3);
                    String text1 = getResources().getString(busort);
                    String text12 = getResources().getString(busort2);

                    textView.setText(busort);
                    textView.setText(busort2);

    }
   public void addback(){
        butto2.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (i > 0){
                    i--;
                    i = i % images.length;     
                    setCurrentImage();
                }

            }

        });

        }
        public void reset(){
            reset_bu.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {

                    i=0;
                    setCurrentImage();

                    }
            });
        }
   }
path
class Tree extends React.Component {
    constructor(props) {
        super(props);
        this.state = { data: props.data }
    }
    render() {
        // Create nested tree structure from data
        let root = { children: {} };
        for (let {spot} of this.state.data) {
            let node = root;
            for (let child of spot.path.match(/..../g)) {
                if (!(child in node.children)) node.children[child] = { children: {} };
                node = node.children[child];
            }
            node.name = spot.landmark_name;
            if (spot.distance) node.distance = String(+spot.distance) + spot.unit;
        }
        // Create elements from tree
        const e = React.createElement;
        return (function recur(node, level=1) {
            let children = Object.values(node.children).map(child => recur(child, level+1));
            if (children.length === 1 && !node.name) return children[0];
            if (!children.length) children = [e("p", null, node.distance)];
            if (node.name) children.unshift(e("h" + level, null, node.name));
            return e("div", null, ...children);
        })(root);
    }
}

// Sample data from the question:
const data = [{info: { close: [], open: true, level: 1 },spot: {id: 2,path: "00020002",depth: 2,numchild: 0,landmark_name: "Metrolink Trafford Depot",distance: "700.00",unit: "m",child: 0}},{info: { close: [], open: false, level: 1 },spot: {id: 3,path: "00020003",depth: 2,numchild: 0,landmark_name: "Bus Stand",distance: "300.00",unit: "m",child: 0}},{info: { close: [], open: false, level: 1 },spot: {id: 4,path: "00020005",depth: 2,numchild: 2,landmark_name: "Restaurants and Bars",distance: null,unit: null,child: 1}},{info: { close: [], open: true, level: 2 },spot: {id: 5,path: "000200050001",depth: 3,numchild: 2,landmark_name: "Trafford Bar",distance: 650.00,unit: "m",child: 1}},{info: { close: ["0"], open: false, level: 2 },spot: {id: 6,path: "000200050003",depth: 3,numchild: 0,landmark_name: "Café Hardrock",distance: "1.50 ",unit: "km",child: 0}},{info: { close: [], open: false, level: 1 },spot: {id: 8,path: "00020008",depth: 2,numchild: 1,landmark_name: "Hospital",distance: null,unit: null,child: 1}},{info: { close: ["0", "1", "2"], open: true, level: 2 },spot: {id: 14,path: "000200080001",depth: 3,numchild: 0,landmark_name: "Seymour Grove Health Centre",distance: "320.00",unit: "m",child: 0}}];

// Render
ReactDOM.render(React.createElement(Tree, {data}), document.body);