JS替换所有匹配的id值

JS replace all matching id values

一个网站有多个页面从另一个页面导入 HTML,带有需要简化的 id 标签。

目前看起来是这样的。

<h2> 
    <a id="user-content-test1" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2> 
    <a id="user-content-best2" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2> 
    <a id="user-content-nest3" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2> 
    <a id="user-content-rest4" href="https://www.example.com">
        Anything
    </a>
</h2>

有指向所有这些 ID 的锚链接,但这些链接不包括“user-content-”部分。他们看起来像这样 Link 来锚定。他们看起来不像这样 Link 来锚定。这些 ID 太多,无法手动更改。

如何使用 jQuery 或纯 JS 将所​​有 id 标签的值从 id="user-content-test1 更改为仅 id="test1?期望的结果应该是:

<h2> 
    <a id="test1" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2> 
    <a id="best2" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2> 
    <a id="nest3" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2> 
    <a id="rest4" href="https://www.example.com">
        Anything
    </a>
</h2>

我搜索了整个 Whosebug 和 google,但我只找到了如何替换字符串,而不是 ID。我已经尝试了这两个脚本,但没有结果。

<script>
$(document).ready(function(){
let result = 'user-content-'.replaceAll(/\+/g, ' ');
});
</script>
<script>
$(document).ready(function(){
var find = 'user-content-';
var re = new RegExp(find, 'g');

str = str.replace(re, '');});
</script>

您可以非常快速地使用jQuery匹配<h2>标签中的所有<a>标签,然后替换它们的所有id。您的问题可以分解为更小的步骤:

  • 找到一种方法来匹配您想要的元素
  • 想办法获取那些元素的 ID 属性
  • 处理该 ID 属性中的字符串

前两个可以用 jQuery 或纯 JS 来完成,第三个可以用简单的字符串操作来完成,就像 String.slice() 一样,因为“user-content-”是固定的无论如何长度。

使用 select 或 $("h2 a[id^=user-content]") -> 这意味着 select 所有 id 以 user-content

开头

$(document).ready(function() {
  $("h2 a[id^=user-content]").each((i, e) => {

    let id = $(e).attr("id");
    $(e).attr("id", id.replace("user-content-", ""));
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>
  <a id="user-content-test1" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2>
  <a id="user-content-best2" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2>
  <a id="user-content-nest3" href="https://www.example.com">
        Anything
    </a>
</h2>
<h2>
  <a id="user-content-rest4" href="https://www.example.com">
        Anything
    </a>
</h2>

由于问题是您在文档的其他地方有 link 这些特定元素的锚点,我可以想到三种方法来解决问题:

  1. 更改这些元素的 id 以便它们匹配 <a> 元素的片段标识符 linking 到它们(正如您明确提出的问题),或者
  2. 将link的元素的href改成它们;这意味着任何以这些元素为目标的样式都不需要调整它们的选择器。

在每个可能的解决方案中,都有一个相对简单的 JavaScript 和 jQuery 解决方案。

所有方法都将使用以下 HTML 和 CSS:

:root {
  --color: #000f;
  --backgroundColor: #fff;
}

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  line-height: 1.5;
}

nav ul {
  display: flex;
  justify-content: space-around;
  list-style-type: none;
}

nav a:is(:link, :visited) {
  color: var(--color);
  background-color: var(--backgroundColor);
}

nav a:is(:hover, :active, :focus) {
  color: var(--backgroundColor);
  background-color: var(--color);
}

h2 {
  margin-block: 3em;
}

h2 a:is(:link, :visited) {
  background: linear-gradient(90deg, lime, #ffff);
  display: block;
  color: var(--color);
  text-decoration: none;
}

h2 a:is(:hover, :active, :focus) {
  text-decoration: underline;
  text-decoration-thickness: 3px;
}

h2 a:target {
  background: linear-gradient(90deg, #f90, #ffff);
}

h2 a::after {
  content: ' (#' attr(id) ').';
}
<nav id="toc">
  <ul>
    <li><a href="#test1">Link to "test1"</a></li>
    <li><a href="#best2">Link to "best2"</a></li>
    <li><a href="#nest3">Link to "nest3"</a></li>
    <li><a href="#rest4">Link to "rest4"</a></li>
  </ul>
</nav>
<h2>
  <a id="user-content-test1" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-best2" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-nest3" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-rest4" href="https://www.example.com">
    Anything
  </a>
</h2>

因此,直接回答您的问题:如何更改 user-content-* 元素的 id 以删除 user-content- 部分:

首先,使用普通 JavaScript:

// utility function written by: Michał Perłakowski
// (https://whosebug.com/users/3853934/)
// taken from:
// 
// used because the behaviour of Object.assign() doesn't
// work well in merging objects with unspecifed values/keys:
const assign = (target, ...sources) =>
  Object.assign(target, ...sources.map(x =>
    Object.entries(x)
    .filter(([key, value]) => value !== undefined)
    .reduce((obj, [key, value]) => (obj[key] = value, obj), {})
  ));

// defining a named function, which accepts an Object of user-
// defined options in order to change the default behaviour of
// the function; if no Object is passed in the function
// sets the opts variable to an empty Object:
function removeTextFromAttribute(opts = {}) {

  // these are the default settings for the function:
  let defaults = {
      // String, accepts a CSS selector to select the
      // relevant elements:
      elements: 'a',
      // String, accepts the attribute-name from which
      // you wish to remove characters:
      attribute: 'id',
      // String, the string you wish to remove from
      // those attributes:
      remove: 'user-content-',
      // Boolean, does the attribute start with the String
      // you wish to remove:
      startsWith: false,
      // Boolean, does the attribute end with the String
      // you wish to remove:
      endsWith: false,
    },

    // here we use the utility function (cited above) in
    // order to compensate for the behaviour of the
    // native Object.assign() functionality (see the
    // question related to the linked answer). It
    // seems that objects later in the argument-list of
    // the function overwrite declared keys of previous
    // Objects, and we want the user to overwrite the
    // defaults; so remember to put the user-defined
    // opts Object last in order that it overwrites
    // the defaults:
    settings = assign({}, defaults, opts);

  // using Object destructuring assignment to assign the
  // resulting options to named variables (mainly to avoid
  // having to type settings.elements, settings.attribute...):
  const {
    elements,
    attribute,
    remove,
    startsWith,
    endsWith
  } = settings;

  // declaring a variable, without initialising it:
  let selector;

  // if the user sets both the startsWith and EndsWith value
  // to true, then the attribute-value to be changed may either
  // be equal to the provided String or it may both begin and
  // start with the provided string; to simplify selection in
  // these cases we set the selector variable to '*=' which
  // selects an element with the attribute, and an attribute-
  // value appears within the String at least once. Otherwise
  // if the startsWith and endsWith are both false this implies
  // that the remove String appears within the attribute-value
  // somewhere, so we also use the '*=' selector:
  if ((startsWith && endsWith) || (!startsWith && !endsWith)) {
    selector = '*=';

    // if startsWith is true and endsWith is not, we use the
    // attribute-value-starts with selector:
  } else if (startsWith && !endsWith) {
    selector = '^=';
    // finally if startsWith is falsey, and endsWith is true:
    // we use the attribute-value-ends-with selector:
  } else if (!startsWith && endsWith) {
    selector = '$=';
  }

  // here we use document.querySelectorAll to select all
  // elements that match the created-selector, which takes
  // the form of: 'Element[attribute<selector>"StringToRemove"]',
  // for example: 'a[id^="user-content-"]'
  const haystack = document.querySelectorAll(
    // we use a template literal string to interpolate the
    // various variables into the resulting String, this is
    // in order to avoid having to concatenate Strings and
    // variables:
    `${elements}[${attribute}${selector}"${remove}"]`
  );

  // we use NodeList.prototype.forEach() to iterate over the 
  // list of Nodes returned:
  haystack.forEach(
    // we use an Arrow function, since we have no need to use
    // 'this'; 'el' is a reference to the current Node of the
    // NodeList over which we're iterating:
    (el) => {
      // we use Element.getAttribute to retrieve the attribute
      // to be modified:
      let attr = el.getAttribute(attribute);

      -
    });
}

// calling the named function, in this case with all the default
// settings and passing no arguments as the defaults are set to
// your specified functionality:
removeTextFromAttribute();
:root {
  --color: #000f;
  --backgroundColor: #fff;
}

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  line-height: 1.5;
}

nav ul {
  display: flex;
  justify-content: space-around;
  list-style-type: none;
}

nav a:is(:link, :visited) {
  color: var(--color);
  background-color: var(--backgroundColor);
}

nav a:is(:hover, :active, :focus) {
  color: var(--backgroundColor);
  background-color: var(--color);
}

h2 {
  margin-block: 3em;
}

h2 a:is(:link, :visited) {
  background: linear-gradient(90deg, lime, #ffff);
  display: block;
  color: var(--color);
  text-decoration: none;
}

h2 a:is(:hover, :active, :focus) {
  text-decoration: underline;
  text-decoration-thickness: 3px;
}

h2 a:target {
  background: linear-gradient(90deg, #f90, #ffff);
}

h2 a::after {
  content: ' (#' attr(id) ').';
}
<nav id="toc">
  <ul>
    <li><a href="#test1">Link to "test1"</a></li>
    <li><a href="#best2">Link to "best2"</a></li>
    <li><a href="#nest3">Link to "nest3"</a></li>
    <li><a href="#rest4">Link to "rest4"</a></li>
  </ul>
</nav>
<h2>
  <a id="user-content-test1" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-best2" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-nest3" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-rest4" href="https://www.example.com">
    Anything
  </a>
</h2>

与 jQuery:

// here we're creating a jQuery plugin using the IIFE - Immediately-
// Invoked Function Expression - approach:
(function($) {

  // defining the name of the plugin, and passing in the opts argument:
  $.fn.removeTextFromAttribute = function(opts) {
    // defining the defaults (as above), although we're not
    // defining the element-types upon which we wish to work
    // as jQuery passes that collection to the plugin:
    let defaults = {
        attribute: 'id',
        remove: 'user-content-',
        startsWith: false,
        endsWith: false,
      },
      // a far easier means of combining the user-defined
      // properties with the default properties (bear in
      // mind this is simple because the library has taken
      // care of it elsewhere, so it's more concise for
      // yourself but obviously including the whole library
      // has its own cost/benefit analysis to be undertaken):
      settings = $.extend(defaults, opts);

    // again using destructuring assignment:
    const {
      attribute,
      remove,
      startsWith,
      endsWith
    } = settings;

    // declaring, but not initialising, the 'selector' variable:
    let selector;

    if ((startsWith && endsWith) || (!startsWith && !endsWith)) {
      selector = '*=';
    } else if (startsWith && !endsWith) {
      selector = '^=';
    } else if (!startsWith && endsWith) {
      selector = '$=';
    }

    // using a template String to create the attribute-selector:
    selectorString = `[${attribute}${selector}"${remove}"]`

    // here we return the results of these chained method calls,
    // first we use the filter() method:
    return this.filter(function(index, elem) {

      // we use a native JavaScript Element.matches method
      // to establish whether the current Node of the jQuery
      // collection matches the selector string we've
      // created above; if yes (Boolean true) that node is
      // retained in the collection, if not (Boolean false)
      // the current Node is discarded from the collection:
      return this.matches(selectorString);
      
      // next we use the attr() method as a setter, in order
      // to modify the named attribute, and use the 
      // anonymous callback function to modify each attribute
      // in turn:
    }).attr(attribute, function(i, attr) {

      // this is exactly the same as the above - Plain
      // JavaScript - version:
      if (attr === remove) {
        this.removeAttribute(attribute);
      } else if (attr.includes(remove)) {
        this.setAttribute(
          attribute,
          attr.replace(new RegExp(remove, 'g'), ''));
      }
    });
  }

  // passing jQuery into the function:
}(jQuery));

// note that here we selected all <a> elements, this forms
// the collection passed to the jQuery plugin and is why
// we didn't need to specify the attribute-type within the
// plugin:
$('a').removeTextFromAttribute();
:root {
  --color: #000f;
  --backgroundColor: #fff;
}

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  line-height: 1.5;
}

nav ul {
  display: flex;
  justify-content: space-around;
  list-style-type: none;
}

nav a:is(:link, :visited) {
  color: var(--color);
  background-color: var(--backgroundColor);
}

nav a:is(:hover, :active, :focus) {
  color: var(--backgroundColor);
  background-color: var(--color);
}

h2 {
  margin-block: 3em;
}

h2 a:is(:link, :visited) {
  background: linear-gradient(90deg, lime, #ffff);
  display: block;
  color: var(--color);
  text-decoration: none;
}

h2 a:is(:hover, :active, :focus) {
  text-decoration: underline;
  text-decoration-thickness: 3px;
}

h2 a:target {
  background: linear-gradient(90deg, #f90, #ffff);
}

h2 a::after {
  content: ' (#' attr(id) ').';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav id="toc">
  <ul>
    <li><a href="#test1">Link to "test1"</a></li>
    <li><a href="#best2">Link to "best2"</a></li>
    <li><a href="#nest3">Link to "nest3"</a></li>
    <li><a href="#rest4">Link to "rest4"</a></li>
  </ul>
</nav>
<h2>
  <a id="user-content-test1" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-best2" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-nest3" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-rest4" href="https://www.example.com">
    Anything
  </a>
</h2>

第二种方法——将link的<a>个元素的href属性更新为这些<a> 元素与上面使用的方法非常相似,但显然我们是 inserting/updating 属性值而不是从中删除。所以这将需要一个新函数,如下所示:

首先,使用普通 JavaScript:

// utility function written by: Michał Perłakowski
// (https://whosebug.com/users/3853934/)
// taken from:
// 
// used because the behaviour of Object.assign() doesn't
// work well in merging objects with unspecifed values/keys:
const assign = (target, ...sources) =>
  Object.assign(target, ...sources.map(x =>
    Object.entries(x)
    .filter(([key, value]) => value !== undefined)
    .reduce((obj, [key, value]) => (obj[key] = value, obj), {})
  ));

// new named function, set up in the same way as above,
// albeit with new arguments:
function insertTextIntoAttribute(opts = {}) {
  let defaults = {
      attribute: 'id',
      elements: 'a',
      // Boolean, do you wish to insert the new String
      // at the end of the current value?
      endWith: false,
      // String, the string you wish to insert:
      insert: 'user-content-',
      // Boolean, do you wish to insert the new String
      // at the start of the current value?
      startWith: true,
    },
    settings = assign({}, defaults, opts);

  const {
    elements,
    attribute,
    insert,
    startWith,
    endWith
  } = settings,
  // using a template literal to create a simple selector
  // to find the elements that match your requirements:
  selectorString = `${elements}`;

  // using document.querySelectorAll() to retrieve a 
  // NodeList of elements that match the selector
  // passed to the function:
  const haystack = document.querySelectorAll(
    selectorString
  );

  // NodeList.prototype.forEach() to iterate over the
  // returned NodeList:
  haystack.forEach(
    (el) => {
      // we retrieve the current attribute-value of the
      // relevant element:
      let currentValue = el.getAttribute(attribute),
        // because a hash requires some special consideration
        // (the '#' character has to be at the beginning) we
        // initialise this variable to false:
        isHash = false;

      // we use Element.matches to see if the current element
      // of the NodeList is an <a> element (we could have instead
      // used el.tagName === 'A') but Element.matches is
      // more concise, easier to read and doesn't require a
      // comparison), it is we then check if the current attribute-
      // value matches the <a> element's hash:
      if (el.matches('a') && currentValue === el.hash) {
        // if it does we then update the isHash variable to true:
        isHash = true;
      }

      // here we use Element.setAttribute() to update the named
      // attribute (first argument) to a new value:
      el.setAttribute(attribute,

        // this is perhaps a little confusing to read, as we're
        // taking advantage of Template strings' ability to
        // interpolate a variable into the String, and we're
        // using conditional operators to do so. In order:
        // 1. ${isHash ? '#' : ''}
        // we test isHash; if true/truthy
        // the expression returns the '#' character, if false/falsey
        // the expression returns the empty String ''.
        // 2. ${startWith ? insert : ''}
        // we test startWith; if true/truthy the expression returns
        // the 'insert' variable's value, otherwise if startWith is
        // false/falsey the expression returns the empty-string.
        // 3. ${isHash ? currentValue.replace('#','')
        // here we again test the isHash variable, and if true/truthy
        // the expression returns the result of calling
        // String.prototype.replace() on the current attribute-value
        // of the element; if isHash is false/falsey then it simply
        // returns the current attribute-value.
        // 4. ${endWith ? insert : ''}
        // this is exactly the same as the earlier assessment for
        // the startWith variable, if true/truthy we return the
        // content of the insert variable, otherwise if false/falsey
        // we return an empty String:
        `${isHash ? '#' : ''}${startWith ? insert : ''}${isHash ? currentValue.replace('#','') : currentValue}${endWith ? insert : ''}`
      );
    });
}

// here we call the function, specifying our
// options:
insertTextIntoAttribute({
  // we wish to modify the 'href' attribute:
  attribute: 'href',
  // and we're selecing the <a> elements inside of <li> elements
  // inside of the <nav> element:
  elements: 'nav li a',
});
:root {
  --color: #000f;
  --backgroundColor: #fff;
}

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  line-height: 1.5;
}

nav ul {
  display: flex;
  justify-content: space-around;
  list-style-type: none;
}

nav a:is(:link, :visited) {
  color: var(--color);
  background-color: var(--backgroundColor);
}

nav a:is(:hover, :active, :focus) {
  color: var(--backgroundColor);
  background-color: var(--color);
}

h2 {
  margin-block: 3em;
}

h2 a:is(:link, :visited) {
  background: linear-gradient(90deg, lime, #ffff);
  display: block;
  color: var(--color);
  text-decoration: none;
}

h2 a:is(:hover, :active, :focus) {
  text-decoration: underline;
  text-decoration-thickness: 3px;
}

h2 a:target {
  background: linear-gradient(90deg, #f90, #ffff);
}

h2 a::after {
  content: ' (#' attr(id) ').';
}
<nav id="toc">
  <ul>
    <li><a href="#test1">Link to "test1"</a></li>
    <li><a href="#best2">Link to "best2"</a></li>
    <li><a href="#nest3">Link to "nest3"</a></li>
    <li><a href="#rest4">Link to "rest4"</a></li>
  </ul>
</nav>
<h2>
  <a id="user-content-test1" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-best2" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-nest3" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-rest4" href="https://www.example.com">
    Anything
  </a>
</h2>

与 jQuery:

// here we're creating a jQuery plugin using the IIFE - Immediately-
// Invoked Function Expression - approach:
(function($) {

  // defining the name of the plugin, and passing in the opts argument:
  $.fn.insertTextToAttribute = function(opts) {
    // defining the defaults (as above), although again we're not
    // defining the element-types upon which we wish to work
    // as jQuery passes that collection to the plugin:
    let defaults = {
        attribute: 'id',
        endWith: false,
        insert: 'user-content-',
        startWith: false,
      },

      settings = $.extend(defaults, opts);

    // again using destructuring assignment:
    const {
      attribute,
      insert,
      startWith,
      endWith
    } = settings;

    // we're not filtering the collection here, since jQuery has
    // already taken care of finding the relevant <a> elements and
    // we don't need to select according to current attribute-values
    // since we're modifying them we may not know what they currently
    // are:
    return this.attr(attribute, function(i, attr) {

      // setting isHash to false:
      let isHash = false;

      // as above, we're using this - as jQuery makes that available
      // within its methods - and again using Element.matches, along
      // with checking that the current attribute-value - passed to
      // function automatically from jQuery - is equal to the current
      // hash of the element:
      if (this.matches('a') && attr === this.hash) {
        // if both those checks return true, we update the value to
        // true
        isHash = true;
      }
      
      // note that we could have written the above in the following way:
      // let isHash = this.matches('a') && attr === this.hash;
      // but using an if feels more readable (despite my subsequent
      // code)


      // this is almost the same as the above approach, using conditional
      // operators within template strings to interpolate various variables
      // into the string. The difference is that the 'currentValue'
      // variable was changed to the 'attr' variable-name (for no particular
      // reason):
      return `${isHash ? '#' : ''}${startWith ? insert : ''}${isHash ? attr.replace('#','') : attr}${endWith ? insert : ''}`

    });
  }

// passing jQuery into the function:
}(jQuery));

// selecting all <a> elements on the page that are within <li> elements
// and wrapped within a <nav> element:
$('nav li a').insertTextToAttribute({
  attribute: 'href',
  insert: 'user-content-',
  startWith: true
});
:root {
  --color: #000f;
  --backgroundColor: #fff;
}

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  line-height: 1.5;
}

nav ul {
  display: flex;
  justify-content: space-around;
  list-style-type: none;
}

nav a:is(:link, :visited) {
  color: var(--color);
  background-color: var(--backgroundColor);
}

nav a:is(:hover, :active, :focus) {
  color: var(--backgroundColor);
  background-color: var(--color);
}

h2 {
  margin-block: 3em;
}

h2 a:is(:link, :visited) {
  background: linear-gradient(90deg, lime, #ffff);
  display: block;
  color: var(--color);
  text-decoration: none;
}

h2 a:is(:hover, :active, :focus) {
  text-decoration: underline;
  text-decoration-thickness: 3px;
}

h2 a:target {
  background: linear-gradient(90deg, #f90, #ffff);
}

h2 a::after {
  content: ' (#' attr(id) ').';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav id="toc">
  <ul>
    <li><a href="#test1">Link to "test1"</a></li>
    <li><a href="#best2">Link to "best2"</a></li>
    <li><a href="#nest3">Link to "nest3"</a></li>
    <li><a href="#rest4">Link to "rest4"</a></li>
  </ul>
</nav>
<h2>
  <a id="user-content-test1" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-best2" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-nest3" href="https://www.example.com">
    Anything
  </a>
</h2>
<h2>
  <a id="user-content-rest4" href="https://www.example.com">
    Anything
  </a>
</h2>

由于 Stack Overflow 答案的字符限制,我无法包含拦截浏览器对 <a> 元素的点击事件的方法,尽管我想它已经在其他地方写过。无论如何,希望您至少能够从答案中学到一些有用的东西。