Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

给自定义组件属性绑定值的问题,谢谢 #774

Open
jingxin2015 opened this issue Jan 2, 2024 · 10 comments
Open

给自定义组件属性绑定值的问题,谢谢 #774

jingxin2015 opened this issue Jan 2, 2024 · 10 comments

Comments

@jingxin2015
Copy link

jingxin2015 commented Jan 2, 2024

我现在自定义了一个组件,比如是 xui-checkbox ,组件有一个 checked 属性,支持双向绑定,我现在想绑定一个函数,如下:
image

是做一个表格的全选列,现在在点击全选 checkAll 的时候,会把所有的数据的 id 都存到 checkedMap 这个map里,但是表格数据行里的 checkbox 并没有选中,尝试把 checkedMap 换成一个普通对象也没有效果,请问怎么样才能实现这个效果呢?

@errorrik
Copy link
Contributor

这个场景,玩法很多。一个建议是,全选的 checkbox 不要用双向绑定。下面列表的要不要双向绑定都行

const App = san.defineComponent({
    template: `<div>
        <label><input type="checkbox" checked="{{checkedAll}}" on-change="checkAllChange">select all</label>
        <label s-for="item in items"><input type="checkbox" value="{{item.text}}" checked="{=values=}">{{item.text}}</label>
    </div>`,

    computed: {
        checkedAll() {
            let items = this.data.get('items');
            let values = this.data.get('values');

            // 不严谨
            return items.length === values.length;
        }
    },

    checkAllChange() {
        let checkedAll = this.data.get('checkedAll');
        this.data.set(
            'values', 
            checkedAll ? [] : this.data.get('items').map(item => item.text)
        );
    }
});

let app = new App({
    data: {
        items: [
            {text: 'item1'},
            {text: 'item2'},
            {text: 'item3'}
        ],
        values: []
    }
});

app.attach(document.body);

@jingxin2015
Copy link
Author

jingxin2015 commented Jan 17, 2024 via email

@errorrik
Copy link
Contributor

可以稍微换下思路,用 item 的 checked 来双绑,checkAll 不要双榜。没有本质区别

const CheckBox = san.defineComponent({
    template: `
        <label>
            <input type="checkbox" checked="{=checked=}">{{label}}
        </label>
    `
});

const App = san.defineComponent({
    components: {
        'my-cb': CheckBox
    },

    template: `
        <div>
            <label><input type="checkbox" checked="{{checkedAll}}" on-change="checkAllChange">select all</label>
            <my-cb s-for="item in items" label="{{item.text}}" checked="{=item.checked=}"></my-cb>
        </div>
    `,

    computed: {
        checkedAll() {
            let items = this.data.get('items');
            let len = items.length;

            while (len--) {
                if (!items[len].checked) {
                    return false;
                }
            }

            return true;
        }
    },

    checkAllChange() {
        let checkedAll = this.data.get('checkedAll');
        let items = this.data.get('items');
        let newItems = [];

        for (let i = 0, len = items.length; i < len; i++) {
            newItems.push({
                text: items[i].text,
                checked: !checkedAll
            });
        }
        this.data.set('items', newItems);
    }
});

let app = new App({
    data: {
        items: [
            {text: 'item1'},
            {text: 'item2'},
            {text: 'item3'}
        ]
    }
});

app.attach(document.body);

@jingxin2015
Copy link
Author

jingxin2015 commented Jan 19, 2024 via email

@errorrik
Copy link
Contributor

没理解

@jingxin2015
Copy link
Author

jingxin2015 commented Jan 19, 2024 via email

@errorrik
Copy link
Contributor

@jingxin2015 我看懂了,但是不确定你具体是怎么写的。上代码吧

@jingxin2015
Copy link
Author

jingxin2015 commented Jan 30, 2024 via email

@errorrik
Copy link
Contributor

errorrik commented Feb 2, 2024

我不知道是什么原因导致你的 item 的格式不统一,从而需要 uniquePropertyNames 来控制。但是既然有uniquePropertyNames,说明数据的处理方式也是有迹可循的。你有两种方式处理:

  1. 提前对数据进行处理,通过 computed,或者传给组件之前
  2. 就算是使用 filter 或 method,使用自定义组件也一样能用绑定,做法和之前也没有区别
const CheckBox = san.defineComponent({
    template: `
        <label>
            <input type="checkbox" checked="{=checked=}">{{label}}
        </label>
    `
});

const App = san.defineComponent({
    components: {
        'my-cb': CheckBox
    },

    template: `
        <div>
            <label><input type="checkbox" checked="{{checkedAll}}" on-change="checkAllChange">select all</label>
            <my-cb s-for="item in items" label="{{itemLabel(item, itemNames)}}" checked="{=item.checked=}"></my-cb>
        </div>
    `,

    computed: {
        checkedAll() {
            let items = this.data.get('items');
            let len = items.length;

            while (len--) {
                if (!items[len].checked) {
                    return false;
                }
            }

            return true;
        }
    },

    itemLabel(item, names) {
        return names.map(name => item[name]).join('-');
    },

    checkAllChange() {
        let checkedAll = this.data.get('checkedAll');
        let items = this.data.get('items');
        let newItems = [];

        for (let i = 0, len = items.length; i < len; i++) {
            newItems.push(Object.assign({}, items[i], {checked: !checkedAll}));
        }
        this.data.set('items', newItems);
    }
});

let app = new App({
    data: {
        items: [
            {text: 'item1', text2: '1'},
            {text: 'item2', text2: '2'},
            {text: 'item3', text2: '3'}
        ],
        itemNames: ['text', 'text2']
    }
});

app.attach(document.body);

@errorrik
Copy link
Contributor

errorrik commented Feb 2, 2024

我现在还有另外一个问题,关于路由的,因为我们一开始做的系统没有登录页面,所以参考的(https://baidu.github.io/san/practice/san-router-spa/)这篇文章来做的路由,Home 是一个根组件,附加到页面的 app 元素上,其他是业务逻辑子组件,我现在想添加一个 登录页面,但是这个登录页面应该也是附加到 app 元素上的,因为 Home 页面有一些固定的信息,比如顶部导航之类的,其他页面还要有逻辑控制能跳转到登录页,这个怎么实现呢?谢谢!

这个问题也有两种方式处理,使用 san-router:

  1. 路由变化的时候,组件渲染的目标 dom 是可以配置 target 的。你可以有个固定结构,只让路由控制变化区域 https://baidu.github.io/san-router/docs/guide/add-route
  2. 使用 withRoute 嵌套路由。https://baidu.github.io/san-router/docs/guide/nested-routes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants