angular.service vs angular.factory

本文翻译自:angular.service vs angular.factory

I have seen both angular.factory() and angular.service() used to declare services; 我见过用于声明服务的angular.factory()angular.service() ; however, I cannot find angular.service anywhere in official documentation. 但是,我在官方文档中找不到 angular.service

What is the difference between the two methods? 这两种方法有什么区别? Which should be used for what (assuming they do different things)? 应该用什么(假设他们做不同的事情)?


#1楼

参考:https://stackoom.com/question/y6RX/angular-service-vs-angular-factory


#2楼

Here are the primary differences: 以下是主要差异:

Services 服务

Syntax: module.service( 'serviceName', function ); 语法: module.service( 'serviceName', function );

Result: When declaring serviceName as an injectable argument you will be provided with the instance of a function passed to module.service . 结果:将serviceName声明为injectable参数时,将向您提供传递给module.service 的函数实例

Usage: Could be useful for sharing utility functions that are useful to invoke by simply appending ( ) to the injected function reference. 用法:通过简单地向注入的函数引用附加( )共享对调用有用的实用程序函数非常有用。 Could also be run with injectedArg.call( this ) or similar. 也可以使用injectedArg.call( this )或类似的方式运行。

Factories 工厂

Syntax: module.factory( 'factoryName', function ); 语法: module.factory( 'factoryName', function );

Result: When declaring factoryName as an injectable argument you will be provided with the value that is returned by invoking the function reference passed to module.factory . 结果:当将factoryName声明为injectable参数时,将通过调用传递给module.factory 的函数引用来提供返回

Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances. 用法:用于返回一个'class'函数,然后可以用来创建实例。

Here is example using services and factory . 这是使用服务和工厂的示例 Read more about AngularJS Service vs Factory . 阅读更多关于AngularJS Service vs Factory的信息

You can also check the AngularJS documentation and similar question on stackoverflow confused about service vs factory . 您还可以检查AngularJS文档以及有关服务与工厂混淆的 stackoverflow上的类似问题。


#3楼

Simply put .. 简单的说 ..

// Service
service = (a, b) => {
  a.lastName = b;
  return a;
};

// Factory
factory = (a, b) => Object.assign({}, a, { lastName: b });

 const fullName = { firstName: 'john' }; // Service const lastNameService = (a, b) => { a.lastName = b; return a; }; console.log(lastNameService(fullName, 'doe')); // Factory const lastNameFactory = (a, b) => Object.assign({}, a, { lastName: b }) console.log(lastNameFactory(fullName, 'doe')); 


#4楼

  angular.service('myService', myServiceFunction);
  angular.factory('myFactory', myFactoryFunction);

I had trouble wrapping my head around this concept until I put it to myself this way: 我无法绕过这个概念,直到我这样说:

Service : the function that you write will be new -ed: 服务 :你编写的函数将是新的

  myInjectedService  <----  new myServiceFunction()

Factory : the function (constructor) that you write will be invoked : Factory :将调用您编写的函数 (构造函数):

  myInjectedFactory  <---  myFactoryFunction()

What you do with that is up to you, but there are some useful patterns... 你用它做什么取决于你,但有一些有用的模式......

Such as writing a service function to expose a public API: 比如编写一个服务函数来公开一个公共API:

function myServiceFunction() {
  this.awesomeApi = function(optional) {
    // calculate some stuff
    return awesomeListOfValues;
  }
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.awesome = myInjectedService.awesomeApi();

Or using a factory function to expose a public API: 或使用工厂函数公开公共API:

function myFactoryFunction() {
  var aPrivateVariable = "yay";

  function hello() {
    return "hello mars " + aPrivateVariable;
  }

  // expose a public API
  return {
    hello: hello
  };
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.hello = myInjectedFactory.hello();

Or using a factory function to return a constructor: 或使用工厂函数返回构造函数:

function myFactoryFunction() {
    return function() {
        var a = 2;
        this.a2 = function() {
            return a*2;
        };
    };
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();

Which one to use?... 哪一个使用?...

You can accomplish the same thing with both. 你可以用两者完成同样的事情。 However, in some cases the factory gives you a little bit more flexibility to create an injectable with a simpler syntax. 但是,在某些情况下, 工厂可以更灵活地创建具有更简单语法的注入。 That's because while myInjectedService must always be an object, myInjectedFactory can be an object, a function reference, or any value at all. 这是因为myInjectedService必须始终是一个对象,myInjectedFactory可以是一个对象,一个函数引用或任何值。 For example, if you wrote a service to create a constructor (as in the last example above), it would have to be instantiated like so: 例如,如果您编写了一个服务来创建构造函数(如上面的上一个示例所示),则必须实例化它:

var myShinyNewObject = new myInjectedService.myFunction()

which is arguably less desirable than this: 这可能比这更不可取:

var myShinyNewObject = new myInjectedFactory();

(But you should be wary about using this type of pattern in the first place because new -ing objects in your controllers creates hard-to-track dependencies that are difficult to mock for testing. Better to have a service manage a collection of objects for you than use new() wily-nilly.) (但是你应该首先考虑使用这种类型的模式,因为你的控制器中的对象会创建难以模拟测试的难以跟踪的依赖关系。最好让服务管理一组对象你比使用new()狡猾的。)


One more thing, they are all Singletons... 还有一件事,他们都是单身人士......

Also keep in mind that in both cases, angular is helping you manage a singleton. 还要记住,在这两种情况下,angular都可以帮助您管理单身人士。 Regardless of where or how many times you inject your service or function, you will get the same reference to the same object or function. 无论您注入服务或功能的位置或次数,您都将获得对同一对象或功能的相同引用。 (With the exception of when a factory simply returns a value like a number or string. In that case, you will always get the same value, but not a reference.) (除了工厂只返回一个数字或字符串之类的值。在这种情况下,您将始终获得相同的值,但不是引用。)


#5楼

TL;DR TL; DR

1) When you're using a Factory you create an object, add properties to it, then return that same object. 1)当您使用工厂时,您创建一个对象,向其添加属性,然后返回该对象。 When you pass this factory into your controller, those properties on the object will now be available in that controller through your factory. 当您将此工厂传递到控制器时,该对象上的这些属性现在将通过您的工厂在该控制器中可用。

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.artist = myFactory.getArtist();
});

app.factory('myFactory', function(){
  var _artist = 'Shakira';
  var service = {};

  service.getArtist = function(){
    return _artist;
  }

  return service;
});


2) When you're using Service , Angular instantiates it behind the scenes with the 'new' keyword. 2)当您使用Service时 ,Angular使用'new'关键字在幕后实例化它。 Because of that, you'll add properties to 'this' and the service will return 'this'. 因此,您将向'this'添加属性,服务将返回'this'。 When you pass the service into your controller, those properties on 'this' will now be available on that controller through your service. 当您将服务传递到控制器时,“this”上的这些属性现在将通过您的服务在该控制器上可用。

app.controller('myServiceCtrl', function($scope, myService){
  $scope.artist = myService.getArtist();
});

app.service('myService', function(){
  var _artist = 'Nelly';
  this.getArtist = function(){
    return _artist;
  }
});



Non TL;DR 非TL; DR

1) Factory 1)工厂
Factories are the most popular way to create and configure a service. 工厂是最流行的创建和配置服务的方式。 There's really not much more than what the TL;DR said. DR说的确没有比TL更多的东西。 You just create an object, add properties to it, then return that same object. 您只需创建一个对象,向其添加属性,然后返回该对象。 Then when you pass the factory into your controller, those properties on the object will now be available in that controller through your factory. 然后,当您将工厂传递到控制器时,该对象上的这些属性现在将通过您的工厂在该控制器中可用。 A more extensive example is below. 下面是一个更广泛的例子。

app.factory('myFactory', function(){
  var service = {};
  return service;
});

Now whatever properties we attach to 'service' will be available to us when we pass 'myFactory' into our controller. 现在,当我们将'myFactory'传递给我们的控制器时,我们可以使用我们附加到'service'的任何属性。

Now let's add some 'private' variables to our callback function. 现在让我们在回调函数中添加一些“私有”变量。 These won't be directly accessible from the controller, but we will eventually set up some getter/setter methods on 'service' to be able to alter these 'private' variables when needed. 这些不能直接从控制器访问,但我们最终会在'service'上设置一些getter / setter方法,以便在需要时能够改变这些'private'变量。

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
   _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK';
    return _finalUrl
  }

  return service;
});

Here you'll notice we're not attaching those variables/function to 'service'. 在这里你会注意到我们没有将这些变量/函数附加到'service'。 We're simply creating them in order to either use or modify them later. 我们只是创建它们以便以后使用或修改它们。

  • baseUrl is the base URL that the iTunes API requires baseUrl是iTunes API所需的基本URL
  • _artist is the artist we wish to lookup _artist是我们希望查找的艺术家
  • _finalUrl is the final and fully built URL to which we'll make the call to iTunes makeUrl is a function that will create and return our iTunes friendly URL. _finalUrl是最终完全构建的URL,我们将调用iTunes makeUrl是一个函数,它将创建并返回我们的iTunes友好URL。

Now that our helper/private variables and function are in place, let's add some properties to the 'service' object. 现在我们的助手/私有变量和函数已经到位,让我们为'service'对象添加一些属性。 Whatever we put on 'service' we'll be able to directly use in whichever controller we pass 'myFactory' into. 无论我们提供什么“服务”,我们都可以直接使用我们通过“myFactory”的控制器。

We are going to create setArtist and getArtist methods that simply return or set the artist. 我们将创建setArtist和getArtist方法,只返回或设置艺术家。 We are also going to create a method that will call the iTunes API with our created URL. 我们还将创建一个方法,使用我们创建的URL调用iTunes API。 This method is going to return a promise that will fulfill once the data has come back from the iTunes API. 一旦数据从iTunes API返回,此方法将返回一个承诺。 If you haven't had much experience using promises in Angular, I highly recommend doing a deep dive on them. 如果你在Angular中没有使用promises的经验,我强烈建议你深入研究它们。

Below setArtist accepts an artist and allows you to set the artist. 以下setArtist接受艺术家并允许您设置艺术家。 getArtist returns the artist callItunes first calls makeUrl() in order to build the URL we'll use with our $http request. getArtist返回艺术家callItunes首先调用makeUrl()以构建我们将用$ http请求使用的URL。 Then it sets up a promise object, makes an $http request with our final url, then because $http returns a promise, we are able to call .success or .error after our request. 然后它设置一个promise对象,使用我们的最终url发出$ http请求,然后因为$ http返回一个promise,我们可以在我们的请求之后调用.success或.error。 We then resolve our promise with the iTunes data, or we reject it with a message saying 'There was an error'. 然后我们使用iTunes数据解决我们的承诺,或者我们拒绝它并显示“有错误”的消息。

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  service.setArtist = function(artist){
    _artist = artist;
  }

  service.getArtist = function(){
    return _artist;
  }

  service.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

  return service;
});

Now our factory is complete. 现在我们的工厂已经完工。 We are now able to inject 'myFactory' into any controller and we'll then be able to call our methods that we attached to our service object (setArtist, getArtist, and callItunes). 我们现在能够将'myFactory'注入任何控制器,然后我们就可以调用附加到服务对象(setArtist,getArtist和callItunes)的方法。

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.data = {};
  $scope.updateArtist = function(){
    myFactory.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myFactory.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

In the controller above we're injecting in the 'myFactory' service. 在上面的控制器中,我们注入了'myFactory'服务。 We then set properties on our $scope object that are coming from data from 'myFactory'. 然后,我们在$ scope对象上设置属性来自'myFactory'的数据。 The only tricky code above is if you've never dealt with promises before. 上面唯一棘手的代码是,如果你以前从未处理过承诺。 Because callItunes is returning a promise, we are able to use the .then() method and only set $scope.data.artistData once our promise is fulfilled with the iTunes data. 因为callItunes正在返回一个promise,所以我们可以使用.then()方法,只有在我们的承诺与iTunes数据一起完成后才设置$ scope.data.artistData。 You'll notice our controller is very 'thin'. 你会注意到我们的控制器非常“薄”。 All of our logic and persistent data is located in our service, not in our controller. 我们所有的逻辑和持久数据都位于我们的服务中,而不是我们的控制器中。

2) Service 2)服务
Perhaps the biggest thing to know when dealing with creating a Service is that that it's instantiated with the 'new' keyword. 在处理创建服务时,最重要的事情可能是它使用'new'关键字进行实例化。 For you JavaScript gurus this should give you a big hint into the nature of the code. 对于JavaScript JavaScript专家来说,这应该会给你一个关于代码本质的一个很大的暗示。 For those of you with a limited background in JavaScript or for those who aren't too familiar with what the 'new' keyword actually does, let's review some JavaScript fundamentals that will eventually help us in understanding the nature of a Service. 对于那些JavaScript背景有限的人或那些不太熟悉'new'关键字实际工作的人,让我们回顾一下最终有助于我们理解服务性质的JavaScript基础知识。

To really see the changes that occur when you invoke a function with the 'new' keyword, let's create a function and invoke it with the 'new' keyword, then let's show what the interpreter does when it sees the 'new' keyword. 要真正看到使用'new'关键字调用函数时发生的更改,让我们创建一个函数并使用'new'关键字调用它,然后让我们看看解释器在看到'new'关键字时的作用。 The end results will both be the same. 最终结果将是相同的。

First let's create our Constructor. 首先让我们创建我的构造函数。

var Person = function(name, age){
  this.name = name;
  this.age = age;
}

This is a typical JavaScript constructor function. 这是一个典型的JavaScript构造函数。 Now whenever we invoke the Person function using the 'new' keyword, 'this' will be bound to the newly created object. 现在每当我们使用'new'关键字调用Person函数时,'this'将绑定到新创建的对象。

Now let's add a method onto our Person's prototype so it will be available on every instance of our Person 'class'. 现在让我们在Person的原型上添加一个方法,这样它就可以在Person'类'的每个实例上使用。

Person.prototype.sayName = function(){
  alert('My name is ' + this.name);
}

Now, because we put the sayName function on the prototype, every instance of Person will be able to call the sayName function in order alert that instance's name. 现在,因为我们将sayName函数放在原型上,所以Person的每个实例都能够调用sayName函数,以便提示实例的名称。

Now that we have our Person constructor function and our sayName function on its prototype, let's actually create an instance of Person then call the sayName function. 现在我们在其原型上有了Person构造函数和sayName函数,让我们实际创建Person的实例然后调用sayName函数。

var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'

So all together the code for creating a Person constructor, adding a function to it's prototype, creating a Person instance, and then calling the function on its prototype looks like this. 因此,创建Person构造函数的代码,向其原型添加函数,创建Person实例,然后在其原型上调用函数就像这样。

var Person = function(name, age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  alert('My name is ' + this.name);
}
var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'

Now let's look at what actually is happening when you use the 'new' keyword in JavaScript. 现在让我们看一下在JavaScript中使用'new'关键字时实际发生的情况。 First thing you should notice is that after using 'new' in our example, we're able to call a method (sayName) on 'tyler' just as if it were an object - that's because it is. 你应该注意的第一件事是在我们的例子中使用'new'后,我们能够在'tyler'上调用一个方法(sayName),就像它是一个对象一样 - 那是因为它是。 So first, we know that our Person constructor is returning an object, whether we can see that in the code or not. 首先,我们知道我们的Person构造函数正在返回一个对象,我们是否可以在代码中看到它。 Second, we know that because our sayName function is located on the prototype and not directly on the Person instance, the object that the Person function is returning must be delegating to its prototype on failed lookups. 其次,我们知道因为我们的sayName函数位于原型而不是直接位于Person实例上,所以Person函数返回的对象必须在失败的查找中委托给它的原型。 In more simple terms, when we call tyler.sayName() the interpreter says “OK, I'm going to look on the 'tyler' object we just created, locate the sayName function, then call it. 换句话说,当我们调用tyler.sayName()时,解释器说“好了,我将查看我们刚创建的'tyler'对象,找到sayName函数,然后调用它。 Wait a minute, I don't see it here - all I see is name and age, let me check the prototype. 等一下,我在这里看不到 - 我只看到名字和年龄,让我查看原型。 Yup, looks like it's on the prototype, let me call it.”. 是的,看起来像是在原型上,让我称之为。“

Below is code for how you can think about what the 'new' keyword is actually doing in JavaScript. 下面是您如何思考'new'关键字在JavaScript中实际执行的操作的代码。 It's basically a code example of the above paragraph. 它基本上是上一段的代码示例。 I've put the 'interpreter view' or the way the interpreter sees the code inside of notes. 我已经把'解释器视图'或解释器看到注释中的代码的方式。

var Person = function(name, age){
  //The line below this creates an obj object that will delegate to the person's prototype on failed lookups.
  //var obj = Object.create(Person.prototype);

  //The line directly below this sets 'this' to the newly created object
  //this = obj;

  this.name = name;
  this.age = age;

  //return this;
}

Now having this knowledge of what the 'new' keyword really does in JavaScript, creating a Service in Angular should be easier to understand. 现在了解“新”关键字在JavaScript中的实际功能,在Angular中创建服务应该更容易理解。

The biggest thing to understand when creating a Service is knowing that Services are instantiated with the 'new' keyword. 创建服务时要了解的最重要的事情是知道服务是使用'new'关键字实例化的。 Combining that knowledge with our examples above, you should now recognize that you'll be attaching your properties and methods directly to 'this' which will then be returned from the Service itself. 将这些知识与上面的示例相结合,您现在应该认识到您将直接将属性和方法附加到'this',然后从服务本身返回。 Let's take a look at this in action. 我们来看看这个实际情况。

Unlike what we originally did with the Factory example, we don't need to create an object then return that object because, like mentioned many times before, we used the 'new' keyword so the interpreter will create that object, have it delegate to it's prototype, then return it for us without us having to do the work. 与我们最初对Factory示例所做的不同,我们不需要创建对象然后返回该对象,因为像之前多次提到的那样,我们使用了'new'关键字,因此解释器将创建该对象,让它委托给它是原型,然后在没有我们完成工作的情况下将它归还给我们。

First things first, let's create our 'private' and helper function. 首先,让我们创建我们的'私人'和帮助函数。 This should look very familiar since we did the exact same thing with our factory. 这应该看起来非常熟悉,因为我们对我们的工厂做了同样的事情。 I won't explain what each line does here because I did that in the factory example, if you're confused, re-read the factory example. 我不会解释每一行在这里的作用,因为我在工厂示例中这样做,如果您感到困惑,请重新阅读工厂示例。

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
});

Now, we'll attach all of our methods that will be available in our controller to 'this'. 现在,我们将把我们控制器中可用的所有方法附加到'this'。

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.setArtist = function(artist){
    _artist = artist;
  }

  this.getArtist = function(){
    return _artist;
  }

  this.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

});

Now just like in our factory, setArtist, getArtist, and callItunes will be available in whichever controller we pass myService into. 现在就像在我们的工厂一样,setArtist,getArtist和callItunes将在我们传递myService的任何控制器中可用。 Here's the myService controller (which is almost exactly the same as our factory controller). 这是myService控制器(几乎与我们的工厂控制器完全相同)。

app.controller('myServiceCtrl', function($scope, myService){
  $scope.data = {};
  $scope.updateArtist = function(){
    myService.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myService.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

Like I mentioned before, once you really understand what 'new' does, Services are almost identical to factories in Angular. 就像我之前提到的,一旦你真正理解了“新”的含义,服务几乎与Angular的工厂相同。


#6楼

app.factory('fn', fn) vs. app.service('fn',fn) app.factory('fn',fn)与app.service('fn',fn)

Construction 施工

With factories, Angular will invoke the function to get the result. 对于工厂,Angular将调用函数来获得结果。 It is the result that is cached and injected. 它是缓存和注入的结果。

 //factory
 var obj = fn();
 return obj;

With services, Angular will invoke the constructor function by calling new . 使用服务,Angular将通过调用new来调用构造函数。 The constructed function is cached and injected. 构造的函数被缓存并注入。

  //service
  var obj = new fn();
  return obj;

Implementation 履行

Factories typically return an object literal because the return value is what's injected into controllers, run blocks, directives, etc 工厂通常返回一个对象文字,因为返回值注入控制器,运行块,指令等的内容

  app.factory('fn', function(){
         var foo = 0;
         var bar = 0;
         function setFoo(val) {
               foo = val;
         }
         function setBar (val){
               bar = val;
         }
         return {
                setFoo: setFoo,
                serBar: setBar
         }
  });

Service functions typically do not return anything. 服务功能通常不返回任何内容。 Instead, they perform initialization and expose functions. 相反,它们执行初始化和公开函数。 Functions can also reference 'this' since it was constructed using 'new'. 函数也可以引用'this',因为它是使用'new'构造的。

app.service('fn', function () {
         var foo = 0;
         var bar = 0;
         this.setFoo = function (val) {
               foo = val;
         }
         this.setBar = function (val){
               bar = val;
         }
});

Conclusion 结论

When it comes to using factories or services they are both very similar. 在使用工厂或服务时,它们都非常相似。 They are injected into a controllers, directives, run block, etc, and used in client code in pretty much the same way. 它们被注入控制器,指令,运行块等,并以几乎相同的方式在客户端代码中使用。 They are also both singletons - meaning the same instance is shared between all places where the service/factory is injected. 它们也都是单例 - 意味着在注入服务/工厂的所有地方之间共享相同的实例。

So which should you prefer? 那你应该选哪个? Either one - they are so similar that the differences are trivial. 任何一个 - 他们是如此相似,以至于差异是微不足道的。 If you do choose one over the other, just be aware how they are constructed, so that you can implement them properly. 如果您确实选择了另一个,请注意它们的构造方式,以便您可以正确实现它们。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值