Javascript 将值列表作为filtertable内容传递
我正在尝试使用带有React的值列表进行筛选 我所有的“标记”都有一个“标记级别”来表示它们的相关性 我希望它“取消”相同的标签(即如果标签“相同”,则不要重复标签)Javascript 将值列表作为filtertable内容传递,javascript,arrays,reactjs,tags,Javascript,Arrays,Reactjs,Tags,我正在尝试使用带有React的值列表进行筛选 我所有的“标记”都有一个“标记级别”来表示它们的相关性 我希望它“取消”相同的标签(即如果标签“相同”,则不要重复标签) 我希望第一行显示“taglevel”为1的所有tag.name 我希望第二行显示“taglevel”为2或更多的所有tag.name 我无法显示和筛选值“标记”。可能是在我的代码笔的第145行附近,我犯了错误 以下是我努力实现的目标: 我把它放在一个密码笔里 我现在尝试了以下方法,但没有成功: 我尝试使用以下方法进行筛选:
- 我希望第一行显示“taglevel”为1的所有tag.name
- 我希望第二行显示“taglevel”为2或更多的所有tag.name
var LevelFilter = React.createClass({
render: function(){
if (!this.props.tags) return null;
return this.props.tags.filter(tag => tag.taglevel === this.props.targetLevel).map(tag => <a onClick={this.props.onClick}>{tag.name}</a>);
}
});
TL;DR
您的数组操作和React组件存在一些严重问题
请记住,React支持一个特定的自上而下的结构,您应该进一步了解它。每个React组件应尽可能多地使用道具,理想情况下,只有一个顶级组件应保持状态
前进的捷径:
el
没有意义,在您的情况下,它指的是PHOTODATA数组中的照片项目、照片中的标签,然后您使用元素
再次表示其他内容。不要过火,但至少要能够识别变量应该做什么更新 要允许多个过滤器,应更新两种方法:
selectTag: function (tag) {
this.setState({
displayedCategories: this.state.displayedCategories.concat([tag])
});
}
tagFilter: function (photo) {
return this.props.displayedCategories.length !== 0 &&
this.props.displayedCategories.every(function(thisTag) {
return photo.tag.some(function (photoTag) {
return photoTag.id === thisTag.id &&
photoTag.taglevel === thisTag.taglevel;
});
});
},
selectTag
现在附加到displayedCategories数组,而不是替换它
tagFilter
现在检查是否至少应用了一个过滤器(删除this.props.displayedCategories.length!==0
以禁用此功能),这样默认情况下它不会显示所有过滤器,然后检查每个照片中是否存在每个选定过滤器,从而使组件增加
还可以进行进一步的改进,例如在某一级别应用过滤器时禁用该级别(每个级别一个选项),或者通过按钮上的颜色或结果上方的标签列表显示应用过滤器的列表
(使用这些最新更改更新代码笔)
好的,你的代码笔有一些问题
首先,在第137行,从对象中提取标记数组:
if(getUniqueCategories.indexOf(el.tag) === -1 ) getUniqueCategories.push(el.tag);
然后,在146上再次提取:
return <LevelFilter onClick={boundClick} targetLevel={1} tags={el.tag} />
返回
第二级:
return <LevelFilter onClick={boundClick} targetLevel={2} tags={el.tag} />
返回
对于这两种情况,应:
return <LevelFilter onClick={boundClick} targetLevel={n} tags={el} />
返回
这就允许出现另一个问题,即LevelFilter不返回有效的React组件(数组无效)
返回this.props.tags.filter(tag=>tag.taglevel===this.props.targetLevel.map(tag=>{tag.name});
应该是
return (
<div>
{
this.props.tags
.filter(tag => tag.taglevel === this.props.targetLevel)
.map(tag => <a onClick={this.props.onClick}>{tag.name}</a>)
}
</div>
);
返回(
{
这是道具标签
.filter(tag=>tag.taglevel===this.props.targetLevel)
.map(标记=>{tag.name})
}
);
在这些改变之后,你应该有一个更接近你想要去的地方的尝试
您还需要进一步研究一些问题,例如boundClick函数无法正常工作,因为您只有一个标记列表,而没有PHOTODATA
然而,这只是最后一个想法。您可能希望将React组件进一步分解
以下是代码笔中的完整代码列表供参考:
var PHOTODATA = [{
"title": "Into the Wild",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Book",
"taglevel": 1,
"id": 2
}
],
"info": []
},{
"title": "Karate Kid",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Kids",
"taglevel": 3,
"id": 4
}
],
"info": []
},
{
"title": "The Alchemist",
"tag": [
{
"name": "Book",
"taglevel": 1,
"id": 2
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Classic",
"taglevel": 2,
"id": 4
},
{
"name": "Words",
"taglevel": 4,
"id": 4
}
],
"info": []
}];
var PhotoGallery = React.createClass({
getInitialState: function() {
return {
displayedCategories: []
};
},
selectTag: function (tag) {
this.setState({
displayedCategories: this.state.displayedCategories.concat([tag])
});
},
resetFilter: function(){
this.setState({
displayedCategories: []
});
},
render: function(){
var uniqueCategories = PHOTODATA.map(function (photo) {
return photo.tag; // tag is a list of tags...
}).reduce(function (uniqueList, someTags) {
return uniqueList.concat(
someTags.filter(function (thisTag) {
return !uniqueList.some(function(uniqueTag) {
return uniqueTag.id === thisTag.id && uniqueTag.taglevel === thisTag.taglevel
});
})
);
}, []);
return (
<div className="overlay-photogallery">
<div className="filter-panel"><b>Tags with taglevel 1 only to be displayed</b>
<PhotoGalleryLevel level={1} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} />
<a className="resetBtn" onClick={this.resetFilter}> Reset Filter </a>
</div>
<div className="filter-panel"><b>Tags with taglevel 2 only to be displayed</b>
<PhotoGalleryLevel level={2} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} />
</div>
<div className="PhotoGallery">
<PhotoDisplay displayedCategories={this.state.displayedCategories} photoData={PHOTODATA} />
</div>
</div>
);
}
});
var PhotoGalleryLevel = React.createClass({
render: function () {
var filteredTags = this.props.tags.filter(function (tag) {
return tag.taglevel === this.props.level;
}.bind(this));
var disabled = this.props.displayedCategories.some(function (tag) {
return tag.taglevel === this.props.level;
}.bind(this));
return (
<div>
{filteredTags.map(function (tag){
return <PhotoGalleryButton tag={tag} selectTag={this.props.selectTag} disabled={disabled} />;
}.bind(this))}
</div>
);
}
});
var PhotoGalleryButton = React.createClass({
onClick: function (e) {
this.props.selectTag(this.props.tag);
},
render: function () {
return (
<a className={this.props.disabled} onClick={this.onClick}>{this.props.tag.name}</a>
);
}
});
var PhotoDisplay = React.createClass({
getPhotoDetails: function (photo) {
console.log(this.props.displayedCategories, photo);
return (
<Photo title={photo.title} name={photo.name} tags={photo.tag} />
);
},
tagFilter: function (photo) {
return this.props.displayedCategories.length !== 0 &&
this.props.displayedCategories.every(function(thisTag) {
return photo.tag.some(function (photoTag) {
return photoTag.id === thisTag.id &&
photoTag.taglevel === thisTag.taglevel;
});
});
},
render: function () {
return (
<div>
{this.props.photoData.filter(this.tagFilter).map(this.getPhotoDetails)}
</div>
);
}
});
var Photo = React.createClass({
getTagDetail: function (tag){
return (
<li>{tag.name} ({tag.taglevel})</li>
);
},
sortTags: function (tagA, tagB) {
return tagA.taglevel - tagB.taglevel;
},
render: function(){
return (
<div className="photo-container" data-title={this.props.title} >
{this.props.title}
<ul>
{this.props.tags.sort(this.sortTags).map(this.getTagDetail)}
</ul>
</div>
);
}
});
ReactDOM.render(<PhotoGallery />, document.getElementById('main'));
var-PHOTODATA=[{
“标题”:“进入野外”,
“标签”:[
{
“名称”:“电影”,
“标记级别”:1,
“id”:1
},
{
“名称”:“冒险”,
“标记级别”:2,
“身份证”:30
},
{
“名称”:“书籍”,
“标记级别”:1,
“id”:2
}
],
“信息”:[]
},{
“头衔”:“空手道小子”,
“标签”:[
{
“名称”:“电影”,
“标记级别”:1,
“id”:1
},
{
“名称”:“冒险”,
“标记级别”:2,
“身份证”:30
},
{
“姓名”:“孩子们”,
“标记级别”:3,
“id”:4
}
],
“信息”:[]
},
{
“头衔”:“炼金术士”,
“标签”:[
{
“名称”:“书籍”,
“标记级别”:1,
“id”:2
},
{
“名称”:“冒险”,
“标记级别”:2,
“身份证”:30
},
{
“名称”:“经典”,
“标记级别”:2,
“id”:4
},
{
“姓名”:“文字”,
“标记级别”:4,
“id”:4
}
],
“信息”:[]
}];
var PhotoGallery=React.createClass({
getInitialState:函数(){
返回{
显示类别:[]
};
},
选择标签:功能(标签){
这是我的国家({
displayedCategories:this.state.displayedCategories.concat([tag])
});
},
resetFilter:function(){
这是我的国家({
显示类别:[]
});
},
render:function(){
var uniqueCategories=PHOTODATA.map(函数(照片){
return photo.tag;//tag是标记的列表。。。
return this.props.tags.filter(tag => tag.taglevel === this.props.targetLevel).map(tag => <a onClick={this.props.onClick}>{tag.name}</a>);
return (
<div>
{
this.props.tags
.filter(tag => tag.taglevel === this.props.targetLevel)
.map(tag => <a onClick={this.props.onClick}>{tag.name}</a>)
}
</div>
);
var PHOTODATA = [{
"title": "Into the Wild",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Book",
"taglevel": 1,
"id": 2
}
],
"info": []
},{
"title": "Karate Kid",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Kids",
"taglevel": 3,
"id": 4
}
],
"info": []
},
{
"title": "The Alchemist",
"tag": [
{
"name": "Book",
"taglevel": 1,
"id": 2
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Classic",
"taglevel": 2,
"id": 4
},
{
"name": "Words",
"taglevel": 4,
"id": 4
}
],
"info": []
}];
var PhotoGallery = React.createClass({
getInitialState: function() {
return {
displayedCategories: []
};
},
selectTag: function (tag) {
this.setState({
displayedCategories: this.state.displayedCategories.concat([tag])
});
},
resetFilter: function(){
this.setState({
displayedCategories: []
});
},
render: function(){
var uniqueCategories = PHOTODATA.map(function (photo) {
return photo.tag; // tag is a list of tags...
}).reduce(function (uniqueList, someTags) {
return uniqueList.concat(
someTags.filter(function (thisTag) {
return !uniqueList.some(function(uniqueTag) {
return uniqueTag.id === thisTag.id && uniqueTag.taglevel === thisTag.taglevel
});
})
);
}, []);
return (
<div className="overlay-photogallery">
<div className="filter-panel"><b>Tags with taglevel 1 only to be displayed</b>
<PhotoGalleryLevel level={1} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} />
<a className="resetBtn" onClick={this.resetFilter}> Reset Filter </a>
</div>
<div className="filter-panel"><b>Tags with taglevel 2 only to be displayed</b>
<PhotoGalleryLevel level={2} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} />
</div>
<div className="PhotoGallery">
<PhotoDisplay displayedCategories={this.state.displayedCategories} photoData={PHOTODATA} />
</div>
</div>
);
}
});
var PhotoGalleryLevel = React.createClass({
render: function () {
var filteredTags = this.props.tags.filter(function (tag) {
return tag.taglevel === this.props.level;
}.bind(this));
var disabled = this.props.displayedCategories.some(function (tag) {
return tag.taglevel === this.props.level;
}.bind(this));
return (
<div>
{filteredTags.map(function (tag){
return <PhotoGalleryButton tag={tag} selectTag={this.props.selectTag} disabled={disabled} />;
}.bind(this))}
</div>
);
}
});
var PhotoGalleryButton = React.createClass({
onClick: function (e) {
this.props.selectTag(this.props.tag);
},
render: function () {
return (
<a className={this.props.disabled} onClick={this.onClick}>{this.props.tag.name}</a>
);
}
});
var PhotoDisplay = React.createClass({
getPhotoDetails: function (photo) {
console.log(this.props.displayedCategories, photo);
return (
<Photo title={photo.title} name={photo.name} tags={photo.tag} />
);
},
tagFilter: function (photo) {
return this.props.displayedCategories.length !== 0 &&
this.props.displayedCategories.every(function(thisTag) {
return photo.tag.some(function (photoTag) {
return photoTag.id === thisTag.id &&
photoTag.taglevel === thisTag.taglevel;
});
});
},
render: function () {
return (
<div>
{this.props.photoData.filter(this.tagFilter).map(this.getPhotoDetails)}
</div>
);
}
});
var Photo = React.createClass({
getTagDetail: function (tag){
return (
<li>{tag.name} ({tag.taglevel})</li>
);
},
sortTags: function (tagA, tagB) {
return tagA.taglevel - tagB.taglevel;
},
render: function(){
return (
<div className="photo-container" data-title={this.props.title} >
{this.props.title}
<ul>
{this.props.tags.sort(this.sortTags).map(this.getTagDetail)}
</ul>
</div>
);
}
});
ReactDOM.render(<PhotoGallery />, document.getElementById('main'));
import React, { Component } from 'react';
import { pluck } from 'underscore';
class Router extends Component {
constructor(props) {
super(props);
this.state = {
filterData: [],
};
this.filterArray = [];
this.PHOTODATA = [{
"title": "Into the Wild",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Book",
"taglevel": 1,
"id": 2
}
],
"info": []
},{
"title": "Karate Kid",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Kids",
"taglevel": 3,
"id": 4
}
],
"info": []
},
{
"title": "The Alchemist",
"tag": [
{
"name": "Book",
"taglevel": 1,
"id": 2
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Classic",
"taglevel": 2,
"id": 4
},
{
"name": "Words",
"taglevel": 4,
"id": 4
}
],
"info": []
}];
}
handleClick(item) {
const findItem = this.filterArray.indexOf(item);
if (findItem === -1) {
this.filterArray.push(item);
} else {
this.filterArray.pop(item);
}
const filterData = [];
if(this.filterArray.length) {
this.PHOTODATA.map((item) => {
const data = pluck(item.tag, 'name');
let count = 0;
// console.log(data);
this.filterArray.map((filterItem) => {
const find = data.indexOf(filterItem);
if(find !== -1) {
count++;
}
});
if(count === this.filterArray.length) {
filterData.push(item);
}
});
}
console.log(this.filterArray);
this.setState({ filterData });
}
render() {
const taglevel1 = [];
const taglevel2 = [];
this.PHOTODATA.map((item) => {
item.tag.map((tagItem) => {
if(tagItem.taglevel === 1) {
const find = taglevel1.indexOf(tagItem.name);
if(find === -1) {
taglevel1.push(tagItem.name);
}
} else {
const find = taglevel2.indexOf(tagItem.name);
if(find === -1) {
taglevel2.push(tagItem.name);
}
}
});
});
const showLevel1 = (item, index) => {
return <span onClick={this.handleClick.bind(this, item)}> {item} </span>
};
const showLevel2 = (item, index) => {
return <span onClick={this.handleClick.bind(this, item)}> {item} </span>
};
const showData = (item, index) => {
return <div>{item.title}</div>
};
return (<div>
<ul>Tag Level 1: {taglevel1.map(showLevel1)}</ul>
<ul>Tag Level 2: {taglevel2.map(showLevel2)}</ul>
<div>Movie Title: {this.state.filterData.map(showData)}</div>
</div>);
}}