2024-08-21



class DoublyLinkedListNode {
  constructor(value) {
    this.value = value;
    this.next = null;
    this.prev = null;
  }
}
 
class DoublyLinkedList {
  constructor() {
    this.head = null;
    this.tail = null;
    this.length = 0;
  }
 
  append(value) {
    const newNode = new DoublyLinkedListNode(value);
    if (this.length === 0) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      newNode.prev = this.tail;
      this.tail = newNode;
    }
    this.length++;
    return this;
  }
 
  delete(value) {
    if (this.length === 0) return null;
 
    let current = this.head;
    while (current.value !== value) {
      if (current.next === null) return null;
      current = current.next;
    }
 
    if (current === this.head) {
      if (this.length === 1) {
        this.head = null;
        this.tail = null;
      } else {
        this.head = this.head.next;
        this.head.prev = null;
        current.next = null;
      }
    } else if (current === this.tail) {
      this.tail = current.prev;
      this.tail.next = null;
      current.prev = null;
    } else {
      current.prev.next = current.next;
      current.next.prev = current.prev;
      current.next = null;
      current.prev = null;
    }
 
    this.length--;
    return current.value;
  }
}

这段代码实现了一个简单的双向链表,包含了添加节点和删除节点的基本操作。添加节点时,如果链表为空,则新节点既是头节点也是尾节点;如果不为空,则新节点成为尾节点,并且其前驱指向当前的尾节点。删除节点时,需要考虑节点位于头部、尾部还是中间的不同情况,并更新相关节点的prev和next指针。

2024-08-21



<template>
  <div id="app">
    <h2>ToDo List</h2>
    <input type="text" v-model="inputValue"/>
    <button @click="handleSubmit">提交</button>
    <ul>
      <li v-for="(item, index) in list" :key="index">
        {{ item }}
        <button @click="handleDelete(index)">删除</button>
      </li>
    </ul>
  </div>
</template>
 
<script>
export default {
  name: 'App',
  data() {
    return {
      inputValue: '',
      list: []
    }
  },
  methods: {
    handleSubmit() {
      if (this.inputValue.trim() === '') {
        alert('输入内容不能为空!');
        return;
      }
      this.list.push(this.inputValue.trim());
      this.inputValue = '';
    },
    handleDelete(index) {
      this.list.splice(index, 1);
    }
  }
}
</script>
 
<style>
#app {
  text-align: center;
}
 
h2 {
  margin-bottom: 20px;
}
 
input {
  margin-bottom: 10px;
  padding: 8px;
}
 
button {
  margin-right: 10px;
  padding: 8px 16px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
 
button:hover {
  background-color: #0056b3;
}
 
ul {
  list-style-type: none;
  padding: 0;
}
 
li {
  margin: 8px;
  padding: 8px;
  background-color: #f9f9f9;
  border: 1px solid #ddd;
}
</style>

这段代码展示了如何使用Vue.js创建一个简单的ToDo List应用。用户可以输入任务,点击提交按钮将其添加到列表中。每个任务旁边有一个删除按钮,点击可以将其从列表中移除。代码中包含了对应的HTML模板、JavaScript脚本和CSS样式,体现了Vue组件化开发的基本流程。

2024-08-21



// 父页面脚本
 
// 监听子页面发送的消息
window.addEventListener('message', function(event) {
  if (event.origin !== 'http://child.example.com') return; // 确保消息来源可信
  if (event.data.type === 'resize') {
    // 根据子页面发送的数据调整父页面的布局
    document.body.style.width = event.data.width + 'px';
    document.body.style.height = event.data.height + 'px';
  }
});
 
// 向子页面发送消息
var iframe = document.getElementById('myIframe');
iframe.onload = function() {
  iframe.contentWindow.postMessage({ type: 'getDimensions' }, 'http://child.example.com');
};
 
// 子页面脚本
 
// 监听父页面发送的消息
window.addEventListener('message', function(event) {
  if (event.origin !== 'http://parent.example.com') return; // 确保消息来源可信
  if (event.data.type === 'getDimensions') {
    // 计算需要发送给父页面的数据
    var dimensions = { type: 'resize', width: document.body.scrollWidth, height: document.body.scrollHeight };
    // 发送尺寸数据给父页面
    window.parent.postMessage(dimensions, 'http://parent.example.com');
  }
});

这个示例展示了如何在遵守同源策略的前提下,通过postMessage方法实现跨文档(父子)通信。父页面监听子页面发送的消息,并根据接收到的数据调整自身布局。子页面也监听父页面发送的消息,并在需要时向父页面发送数据。这里使用了event.origin来确保消息的来源是安全可信的,避免了潜在的安全问题。




import React from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
 
export default class DraggableFlatList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: props.data,
    };
  }
 
  render() {
    return (
      <FlatList
        data={this.state.data}
        keyExtractor={(item, index) => item.key}
        renderItem={({ item, index }) => (
          <TouchableOpacity onPress={() => this.props.onItemPress(item, index)}>
            <View style={styles.item}>
              <Text style={styles.text}>{item.name}</Text>
            </View>
          </TouchableOpacity>
        )}
      />
    );
  }
}
 
const styles = StyleSheet.create({
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
  },
  text: {
    fontSize: 16,
  },
});

这个简单的示例展示了如何创建一个可拖拽的FlatList组件。它使用了React Native和React Native Gesture Handler库,并提供了一个简单的FlatList,其中的列表项可以被拖拽。这个示例可以作为创建自定义拖拽组件的起点,并展示了如何通过props传递数据和事件处理函数。

由于您没有提供具体的错误信息,我将提供一些常见的React Native FlatList问题及其解决方案:

  1. 渲染问题:如果FlatList不显示任何数据,请确保传递给data属性的数组不为空,并且renderItem函数正确实现。
  2. 性能问题:确保你为每个item设置了合适的key属性,以便React Native可以高效地更新UI。
  3. 内存问题:如果FlatList中有大量数据,请考虑使用initialNumToRender属性来减少一开始渲染的item数量,以及使用windowSize来实现滚动时按需加载更多数据。
  4. 错误的数据源:确保你的数据源是一个可迭代的数组,并且在更新数据后使用setState来更新状态,以确保FlatList能够检测到变化。
  5. 样式问题:如果FlatList的项目渲染不正确,检查renderItem中的样式是否正确应用。
  6. 事件处理问题:如果FlatList中的按钮或其他交互元素无法正常工作,请确保正确绑定了事件处理器。

如果您遇到具体的错误信息,请提供详细信息以便获得更精确的解决方案。

这些问题可能由不同的因素引起,以下是一些常见的原因以及相应的解决方法:

  1. 滚动条异常:可能是由于FlatList的内容没有正确计算其尺寸或者渲染问题导致。确保数据源中的每一项都有确定的高度,并且FlatListrenderItem方法返回的组件具有正确的布局。
  2. 滚动条居中:如果你想要FlatList滚动条默认居中,可以使用initialScrollIndex属性来设置初始选中的项。
  3. 滚动条偏移:可能是由于列表项的布局不一致或者FlatList的外部容器样式导致的偏移。确保所有列表项的布局一致,没有外边距或内边距的差异。
  4. 滚动条错位:可能是由于列表项的高度计算错误或者FlatList的布局在动态变化时没有正确更新导致。确保列表项的高度正确,并且在数据更新后能够正确重新渲染FlatList

解决方法需要根据具体问题进行调整,但通常包括以下步骤:

  • 确保列表项的渲染和布局是正确的。
  • 如果使用动态高度,请确保提供getItemLayout属性或使用固定的行高。
  • 检查是否有外部样式或布局导致的冲突。
  • 如果问题仍然存在,可以尝试使用ScrollView替代FlatList,或者在FlatList外层包裹一个滚动容器,并检查其滚动相关的属性和事件。

在实际操作时,可能需要结合React Native的调试工具,如React Native Debugger,来进一步调试和解决问题。




import React from 'react';
import { View, Text } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';
 
const App = () => {
  const data = [
    {
      time: '08:00',
      title: 'Event One',
      description: 'This is the description for the first event',
    },
    {
      time: '12:00',
      title: 'Event Two',
      description: 'This is the description for the second event',
    },
    // ... 更多事件数据
  ];
 
  return (
    <View style={{ flex: 1, padding: 10 }}>
      <Timeline
        data={data}
        circleSize={30}
        circleColor="#546E7A"
        lineColor="#546E7A"
        descriptionStyle={{ color: '#546E7A' }}
        innerCircle={'icon'}
        iconDefaultColor="#546E7A"
        icon={require('./icons/icon.png')}
        renderDescription={(description) => <Text>{description}</Text>}
        renderTitle={(title) => <Text>{title}</Text>}
        renderCircle={(time) => <Text>{time}</Text>}
      />
    </View>
  );
};
 
export default App;

这个例子展示了如何使用react-native-timeline-flatlist组件来创建一个简单的时间轴视图,其中包含了事件的时间、标题和描述。通过自定义渲染函数,可以定制时间轴上的图标、标题和描述的显示方式。

在React Native, Flutter和微信小程序中,创建列表和网格的方法各有不同。以下是各种技术中的示例代码。

  1. React Native:

列表(使用FlatList):




import React from 'react';
import { FlatList, Text, View } from 'react-native';
 
const DATA = [
  { key: 'a', text: 'Alice' },
  { key: 'b', text: 'Bob' },
  // ...
];
 
const App = () => (
  <View style={{ flex: 1, paddingTop: 20 }}>
    <FlatList
      data={DATA}
      renderItem={({ item }) => <Text>{item.text}</Text>}
    />
  </View>
);
 
export default App;

网格(使用FlatList):




import React from 'react';
import { FlatList, Text, View } from 'react-native';
 
const DATA = [...Array(20).keys()];
 
const App = () => (
  <View style={{ flex: 1, paddingTop: 20 }}>
    <FlatList
      data={DATA}
      renderItem={({ item }) => (
        <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
          <Text>{item}</Text>
        </View>
      )}
      numColumns={3} // 设置网格的列数
    />
  </View>
);
 
export default App;
  1. Flutter:

列表(使用ListView):




import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListView.builder(
          itemCount: 10,
          itemBuilder: (context, index) {
            return ListTile(title: Text("Item $index"));
          },
        ),
      ),
    );
  }
}

网格(使用GridView):




import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: GridView.builder(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
          itemCount: 10,
          itemBuilder: (context, index) {
            return Container(
              color: Colors.green,
              child: Center(child: Text("Item $index")),
            );
          },
        ),
      ),
    );
  }
}
  1. 微信小程序:

列表(使用wx:for):




<view>
  <block wx:for="{{list}}" wx:key="index">
    <text>{{item.text}}</text>
  </block>
</view>



Page({
  data: {
 



import React, { useState, useEffect, useCallback } from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
 
const ItemSeparatorComponent = () => (
  <View
    style={{
      height: 1,
      width: "100%",
      backgroundColor: "#ccc",
    }}
  />
);
 
const ListFooterComponent = ({ isLoading }) => {
  if (isLoading) {
    return (
      <View
        style={{
          paddingVertical: 20,
          borderTopWidth: 1,
          borderColor: "#ccc"
        }}
      >
        <ActivityIndicator />
      </View>
    );
  }
  return null;
};
 
const App = () => {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1);
  const [isLoading, setIsLoading] = useState(false);
  const [isRefreshing, setIsRefreshing] = useState(false);
 
  const fetchData = useCallback(async () => {
    if (isLoading) return;
    setIsLoading(true);
 
    try {
      const response = await fetch(
        `https://api.example.com/data?page=${page}`
      );
      const newData = await response.json();
      setData(page === 1 ? newData : [...data, ...newData]);
      setPage(page + 1);
    } catch (error) {
      console.error(error);
    }
 
    setIsLoading(false);
  }, [isLoading, page, data]);
 
  useEffect(() => {
    fetchData();
  }, [fetchData]);
 
  const handleRefresh = useCallback(async () => {
    if (isRefreshing) return;
    setIsRefreshing(true);
    setPage(1);
    setData([]);
    await fetchData();
    setIsRefreshing(false);
  }, [fetchData, isRefreshing]);
 
  return (
    <FlatList
      data={data}
      onEndReached={fetchData}
      onEndReachedThreshold={0.5}
      onRefresh={handleRefresh}
      refreshing={isRefreshing}
      keyExtractor={item => item.id}
      renderItem={({ item }) => (
        <View>
          <Text>{item.title}</Text>
        </View>
      )}
      ItemSeparatorComponent={ItemSeparatorComponent}
      ListFooterComponent={
        <ListFooterComponent isLoading={isLoading} />
      }
    />
  );
};
 
export default App;

这段代码展示了如何使用React Native的FlatList组件来实现一个基本的分页列表。它使用了useState和useEffect来管理组件的状态,并通过useCallback来避免不必要的重渲染。代码中包含了分页加载数据、下拉刷新,以及加载指示器的例子,是一个很好的学习和实践React Native列表分页的例子。

2024-08-19

在JavaScript中,可以使用addEventListener方法为DOM元素添加事件监听器。这样当特定事件发生时,可以执行一些JavaScript代码。

以下是一个简单的例子,演示了如何为一个按钮添加点击事件监听器:




// 获取按钮元素
const myButton = document.getElementById('myButton');
 
// 为按钮添加点击事件监听器
myButton.addEventListener('click', function() {
    alert('按钮被点击了!');
});

在这个例子中,当按钮被点击时,会弹出一个警告框。

addEventListener方法接受两个参数:

  1. 事件名称:一个字符串,指定要监听的事件类型,例如'click''mouseover'等。
  2. 事件处理函数:当事件发生时要执行的函数。

你可以为同一个元素添加多个事件监听器,并且它们会按照被添加的顺序依次触发。如果同一个事件监听器被添加多次,它也会被多次触发。为了避免这种情况,可以使用removeEventListener方法移除不需要的监听器。