日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

shopify二次开发教程_详细教程:如何将Shopify的Storefront API与React和Redux结合使用...

發(fā)布時(shí)間:2023/11/29 编程问答 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 shopify二次开发教程_详细教程:如何将Shopify的Storefront API与React和Redux结合使用... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

shopify二次開(kāi)發(fā)教程

by Chris Frewin

克里斯·弗里溫(Chris Frewin)

詳細(xì)教程:如何將Shopify的Storefront API與React和Redux結(jié)合使用 (A detailed tutorial: how to use Shopify’s Storefront API with React and Redux)

電子商務(wù)為所有人! (…網(wǎng)站,就是?) (E-commerce for all! (…websites, that is ?))

Written by Chris August 2018, updated November, 2018

克里斯(Chris) 2018年8月撰寫(xiě),2018年11月更新

背景與動(dòng)機(jī) (Background and Motivation)

So the motivation here was pretty simple. I wanted my site visitors to be able to browse, search, and select products directly on my custom domain without having to go to our Shopify site.

因此,這里的動(dòng)機(jī)非常簡(jiǎn)單。 我希望網(wǎng)站訪問(wèn)者能夠直接在我的自定義域上瀏覽,搜索和選擇產(chǎn)品,而不必訪問(wèn)我們的Shopify網(wǎng)站。

The secondary motivation is that I’d much rather have my own codebase for a website than use one of Shopify’s factory templates. No offense Shopify team! The templates are modern and clean, but they are rather basic. I’m sure those templates are heavily customizable, but it’s not a stack I know at the moment.

次要?jiǎng)訖C(jī)是,我寧愿擁有自己的網(wǎng)站代碼庫(kù),也不愿使用Shopify的工廠模板之一。 Shopify團(tuán)隊(duì)無(wú)罪! 模板是現(xiàn)代且干凈的,但是它們是非常基本的。 我敢肯定那些模板是高度可定制的,但是目前我還不知道它是一個(gè)堆棧。

So this is the best of both worlds — my custom React site (already built and online ?), with the added API and checkout process of Shopify!

因此,這是兩全其美的方式-我的自定義React網(wǎng)站(已建立并在線運(yùn)行?),并添加了Shopify的API和結(jié)帳流程!

By the end of this tutorial, you’ll be able to add your Shopify products on any page of your site. The only part of the shopping process that will occur on Shopify is when the user clicks ‘Checkout’.

在本教程結(jié)束時(shí),您將可以在網(wǎng)站的任何頁(yè)面上添加Shopify產(chǎn)品。 Shopify上購(gòu)物過(guò)程的唯一部分是用戶(hù)單擊“結(jié)帳”。

I’ve created an empty boilerplate repository for this tutorial as well.

我也為本教程創(chuàng)建了一個(gè)空的樣板存儲(chǔ)庫(kù) 。

The motivation specifically for writing here on Medium was simply that I couldn’t find a tutorial on this process myself — so I decided to make one!

專(zhuān)門(mén)在Medium上寫(xiě)代碼的動(dòng)機(jī)僅僅是因?yàn)槲易约赫也坏疥P(guān)于此過(guò)程的教程-因此,我決定編寫(xiě)一個(gè)!

I’ve been a professional developer for 4 years now, and programming for 7. I’ve worked in tech stacks from old-school Fortran and Perl, to React, Javascript, Python, and Node.

我已有4年的專(zhuān)業(yè)開(kāi)發(fā)人員經(jīng)驗(yàn),并且有7年的編程經(jīng)驗(yàn)。我從事過(guò)從舊式的Fortran和Perl到React,Javascript,Python和Node的技術(shù)堆棧。

Siren Apparel is one of my side project / startup / maker companies that I’ve run for 5 years now, and we’ve donated to 5 different police and fire departments so far!

Siren Apparel是我運(yùn)營(yíng)了5年的副項(xiàng)目/啟動(dòng)/制造商公司之一,到目前為止,我們已向5個(gè)不同的警察和消防部門(mén)捐款!

Let’s finally get started with this tutorial.

最后,讓我們開(kāi)始學(xué)習(xí)本教程。

Shopify的店面API (Shopify’s Storefront API)

The wonderful folks at Shopify have put together the Storefront API. With the Storefront API, you can create React components to add product pictures, product variations, product sizes, a cart, and ‘a(chǎn)dd to cart’ and ‘checkout’ buttons into your own, non-Shopify site.

Shopify的出色人士匯集了Storefront API 。 使用Storefront API,您可以創(chuàng)建React組件以將產(chǎn)品圖片,產(chǎn)品變體,產(chǎn)品尺寸,購(gòu)物車(chē)以及“添加到購(gòu)物車(chē)”和“結(jié)帳”按鈕添加到您自己的非Shopify網(wǎng)站中。

*Note that this tutorial is NOT about Shopify Polaris, which is used to create components in React for Shopify store management itself.

*請(qǐng)注意,本教程與Shopify Polaris無(wú)關(guān) ,后者用于在React for Shopify商店管理本身中創(chuàng)建組件。

入門(mén): react-js-buy存儲(chǔ)庫(kù) (Getting Started: react-js-buy Repository)

Take a look at this React example built by the Shopify team. Most of the code in this tutorial comes from that repository.

看一下Shopify團(tuán)隊(duì)構(gòu)建的這個(gè)React示例 。 本教程中的大多數(shù)代碼都來(lái)自該存儲(chǔ)庫(kù)。

…Did you take a look? Good! ?

…你看了嗎? 好! ?

Now we’re going to hop right into code! Head to your React site’s root folder and install the shopify-buy module via the terminal:

現(xiàn)在,我們將直接跳入代碼! 轉(zhuǎn)到您的React站點(diǎn)的根文件夾,并通過(guò)終端安裝shopify-buy模塊:

cd my-awesome-react-project/npm install --save shopify-buy

(or yarn add shopify-buy if you prefer yarn)

(或者如果您更喜歡yarn yarn add shopify-buy )

Then, in your frontend index.js, (NOT App.js!) you will need to import Client from the JS Buy SDK:

然后,在前端index.js (不是App.js !)中,您需要從JS Buy SDK導(dǎo)入Client :

import Client from 'shopify-buy';

Then add the following configuration object above the ReactDOM.render()call:

然后在ReactDOM.render()調(diào)用上方添加以下配置對(duì)象:

const client = Client.buildClient({ storefrontAccessToken: 'your-access-token', domain: 'your-shopify-url.myshopify.com'});

That’s it for index.js for now — we’ll come back to it soon.

目前,這就是index.js的內(nèi)容-我們將盡快恢復(fù)。

Now we’re going to add in all the components needed for a smooth shopping and checkout experience. Copy all the components from the react-js-buy repository:

現(xiàn)在,我們將添加所需的所有組件,以實(shí)現(xiàn)順暢的購(gòu)物和結(jié)帳體驗(yàn)。 從react-js-buy存儲(chǔ)庫(kù)復(fù)制所有組件:

Cart.js

Cart.js

LineItem.js

LineItem.js

Product.js

Product.js

Products.js

Products.js

VariantSelector.js

VariantSelector.js

We will paste these components into acomponents/shopify/ folder in your src/ folder. You could put these component files anywhere else in the src/ folder, if you wished. The rest of the tutorial assumes you have put them in components/shopify/ .

我們會(huì)將這些組件粘貼到src/文件夾中的components/shopify/文件夾中。 如果需要,可以將這些組件文件放在src/文件夾中的其他任何位置。 本教程的其余部分假定您已將它們放在components/shopify/ 。

修改App.js (Modifying App.js)

App.js will need extensive changes. First, import that Cart component you just copied into your own project:

App.js將需要進(jìn)行大量更改。 首先,將剛復(fù)制的Cart組件導(dǎo)入到自己的項(xiàng)目中:

import Cart from './components/shopify/Cart';

If your App.js component was stateless, like mine, you should be safe copying this entire constructor() function:

如果您的App.js組件像我的一樣是無(wú)狀態(tài)的,則應(yīng)該安全地復(fù)制以下整個(gè)constructor()函數(shù):

constructor() { super(); this.updateQuantityInCart = this.updateQuantityInCart.bind(this); this.removeLineItemInCart = this.removeLineItemInCart.bind(this); this.handleCartClose = this.handleCartClose.bind(this);}

If you already have state, copy only those bind lines. Those three lines are event handler functions that the Shopify cart needs to function properly.

如果您已經(jīng)有狀態(tài),則僅復(fù)制那些bind線。 這三行是Shopify購(gòu)物車(chē)正常運(yùn)行所需的事件處理函數(shù)。

“But what about state for the cart!?”“但是購(gòu)物車(chē)的狀態(tài)呢??”

You may ask; or:

您可能會(huì)問(wèn); 要么:

“What about defining those event handlers for the cart!?”“如何為購(gòu)物車(chē)定義那些事件處理程序呢??”

Indeed, that’s coming, but not yet! ?

確實(shí),那是即將到來(lái)的,但還沒(méi)有! ?

You can then append the <Cart/> component to the bottom of your render() function, before the ending div.

然后,您可以將<Car t />組件附加到y(tǒng)our re render()函數(shù)的底部,在結(jié)束div之前。

In my opinion, the cart should be accessible anywhere in your app. I think it makes sense, then, to put the <Cart/> component in the root component of your app — in other words, App.js:

我認(rèn)為,購(gòu)物車(chē)應(yīng)該可以在您應(yīng)用的任何位置訪問(wèn)。 因此,我認(rèn)為將<Car t />組件放入應(yīng)用程序的根組件中是有意義的—在其他代碼中ords, App.js:

return (<div>...<Cart checkout={this.state.checkout} isCartOpen={this.state.isCartOpen} handleCartClose={this.handleCartClose} updateQuantityInCart={this.updateQuantityInCart} removeLineItemInCart={this.removeLineItemInCart} /></div>);

Again, I haven’t included any code on the event handlers for the cart yet. Additionally, I didn’t address the lack of state components for the cart in App.js.

同樣,我還沒(méi)有在購(gòu)物車(chē)的事件處理程序中包含任何代碼。 此外,我沒(méi)有解決App.js中購(gòu)物車(chē)缺少狀態(tài)組件的問(wèn)題。

There is good reason for this.

這有充分的理由。

About halfway through this project, I realized my products component was of course not in my App.js file.

在這個(gè)項(xiàng)目進(jìn)行到一半的時(shí)候,我意識(shí)到我的產(chǎn)品組件當(dāng)然不在我的App.js文件中。

Instead, it was buried about three children components down.

相反,它被埋在大約三個(gè)子組件中。

So instead of passing products three levels down to children, and then function handlers all the way back up…

因此,與其將產(chǎn)品的三個(gè)層次傳遞給子級(jí),然后再將函數(shù)處理程序一路備份……

I decided to use…

我決定使用...

? Redux!!! ?

Redux !!!

Ugh! I know, I know, Redux, while not being very difficult, is a pain in the %*$! to wire up initially with all the boilerplate required. But, if you are a developer working on an E-commerce store or an E-commerce store owner, think of it this way: Redux will enable you to access the state of the cart from any component or page in our website or webapp.

啊! 我知道,雖然Redux并不困難,但它對(duì)%* $來(lái)說(shuō)是一個(gè)痛苦! 首先連接所需的所有樣板。 但是,如果您是在電子商務(wù)商店中工作的開(kāi)發(fā)人員或電子商務(wù)商店所有者,請(qǐng)這樣考慮:Redux將使您能夠從我們網(wǎng)站或webapp中的任何組件或頁(yè)面訪問(wèn)購(gòu)物車(chē)的狀態(tài)。

This ability will be essential as Siren Apparel expands and we develop more products. As we create more products, I’ll make a separate dedicated store page with all products, while leaving just a handful of featured products on the homepage.

隨著Siren服裝的擴(kuò)展以及我們開(kāi)發(fā)更多產(chǎn)品,這一能力將至關(guān)重要。 隨著我們創(chuàng)建更多產(chǎn)品,我將在所有產(chǎn)品上創(chuàng)建一個(gè)單獨(dú)的專(zhuān)用商店頁(yè)面,同時(shí)在首頁(yè)上僅保留少數(shù)特色產(chǎn)品。

The ability to access the cart is essential if a user shops around a bit, reads some stories or info about Siren Apparel, and then decides to checkout. It doesn’t matter how much they navigate around, nothing from their cart will be lost!

如果用戶(hù)四處逛逛,閱讀一些有關(guān)Siren Apparel的故事或信息, 然后決定結(jié)帳, 那么訪問(wèn)購(gòu)物車(chē)的能力至關(guān)重要。 不管導(dǎo)航多少,他們的購(gòu)物車(chē)都不會(huì)丟失!

So, in short, I decided it’s probably better to implement Redux now while the codebase for our site isn’t too large.

因此,簡(jiǎn)而言之,我認(rèn)為在我們站點(diǎn)的代碼庫(kù)不太大的情況下,現(xiàn)在最好實(shí)現(xiàn)Redux。

使用裸機(jī)最小模板為Shopify Buy SDK實(shí)施Redux (Implementing Redux for Shopify Buy SDK With Bare Minimum Boilerplate)

Install NPM packages redux and react-redux:

安裝NPM軟件包redux和react-redux :

npm install --save redux react-redux

npm install --save redux react-redux

In index.js , import Provider from react-redux and your store from ./store:

在index.js ,從react-redux導(dǎo)入Provider ,并從./store導(dǎo)入您的store :

import { Provider } from 'react-redux';import store from './store';

import { Provider } from 'react-redux'; import store from './store';

Wrap the <Provider> component with the passed store around your&lt;App>;in index.jsto hook up your App to your Redux store:

包裹<Provid ER>組件與p assed商店不要蜘蛛d you [R&L t;App> ;在index.jsto勾你的應(yīng)用程序到您的終極版店:

ReactDOM.render(<Provider store={store}> ? ?<IntlProvider locale={locale} messages={flattenMessages(messages[locale.substring(0, 2)])}> ? ? ?<App locale={locale}/> ? ?</IntlProvider> </Provider>,document.getElementById('root'));

ReactDOM.render( <Provider store={store}> <IntlProvider locale={locale} messages={flattenMessages(messages[locale.substring(0, 2)])}> <App locale={locale}/> </IntlProvider> </Provider>, document.getElementById('root') );

(Note that I also have a <IntlProvider>, but that’s in a different post about how I applied internationalization and localization to dynamically render the content on Siren Apparel’s site. A different story for a different day.)

(請(qǐng)注意,我也有一個(gè)<IntlProvid er>,但這是在另一篇有關(guān)如何應(yīng)用國(guó)際化和本地化來(lái)動(dòng)態(tài)呈現(xiàn)Siren Apparel網(wǎng)站上內(nèi)容的文章中 。關(guān)于另一天的不同故事。)

Now of course we haven’t made a ./store.js file yet. Create your store in store.jsin the src/ root and put this in it:

當(dāng)然,現(xiàn)在我們還沒(méi)有制作./store.js文件。 在src/根目錄下的store.js中創(chuàng)建商店, store.js其放入其中:

import {createStore} from 'redux';import reducer from './reducers/cart';export default createStore(reducer);

import {createStore} from 'redux'; import reducer from './reducers/cart';export default createStore(reducer);

Create your reducers file in src/reducers/cart.js and paste this code:

在src/reducers/cart.js創(chuàng)建您的reducers文件,然后粘貼以下代碼:

// initial stateconst initState = { ?isCartOpen: false, ?checkout: { lineItems: [] }, ?products: [], ?shop: {}}// actionsconst CLIENT_CREATED = 'CLIENT_CREATED'const PRODUCTS_FOUND = 'PRODUCTS_FOUND'const CHECKOUT_FOUND = 'CHECKOUT_FOUND'const SHOP_FOUND = 'SHOP_FOUND'const ADD_VARIANT_TO_CART = 'ADD_VARIANT_TO_CART'const UPDATE_QUANTITY_IN_CART = 'UPDATE_QUANTITY_IN_CART'const REMOVE_LINE_ITEM_IN_CART = 'REMOVE_LINE_ITEM_IN_CART'const OPEN_CART = 'OPEN_CART'const CLOSE_CART = 'CLOSE_CART'// reducersexport default (state = initState, action) => { ?switch (action.type) { ? ?case CLIENT_CREATED: ? ? ?return {...state, client: action.payload} ? ?case PRODUCTS_FOUND: ? ? ?return {...state, products: action.payload} ? ?case CHECKOUT_FOUND: ? ? ?return {...state, checkout: action.payload} ? ?case SHOP_FOUND: ? ? ?return {...state, shop: action.payload} ? ?case ADD_VARIANT_TO_CART: ? ? ?return {...state, isCartOpen: action.payload.isCartOpen, checkout: action.payload.checkout} ? ?case UPDATE_QUANTITY_IN_CART: ? ? ?return {...state, checkout: action.payload.checkout} ? ?case REMOVE_LINE_ITEM_IN_CART: ? ? ?return {...state, checkout: action.payload.checkout} ? ?case OPEN_CART: ? ? ?return {...state, isCartOpen: true} ? ?case CLOSE_CART: ? ? ?return {...state, isCartOpen: false} ? ?default: ? ? ?return state ?}}

// initial state const initState = { isCartOpen: false, checkout: { lineItems: [] }, products: [], shop: {} }// actions const CLIENT_CREATED = 'CLIENT_CREATED' const PRODUCTS_FOUND = 'PRODUCTS_FOUND' const CHECKOUT_FOUND = 'CHECKOUT_FOUND' const SHOP_FOUND = 'SHOP_FOUND' const ADD_VARIANT_TO_CART = 'ADD_VARIANT_TO_CART' const UPDATE_QUANTITY_IN_CART = 'UPDATE_QUANTITY_IN_CART' const REMOVE_LINE_ITEM_IN_CART = 'REMOVE_LINE_ITEM_IN_CART' const OPEN_CART = 'OPEN_CART' const CLOSE_CART = 'CLOSE_CART'// reducers export default (state = initState, action) => { switch (action.type) { case CLIENT_CREATED: return {...state, client: action.payload} case PRODUCTS_FOUND: return {...state, products: action.payload} case CHECKOUT_FOUND: return {...state, checkout: action.payload} case SHOP_FOUND: return {...state, shop: action.payload} case ADD_VARIANT_TO_CART: return {...state, isCartOpen: action.payload.isCartOpen, checkout: action.payload.checkout} case UPDATE_QUANTITY_IN_CART: return {...state, checkout: action.payload.checkout} return {...state, checkout: action.payload.checkout} case REMOVE_LINE_ITEM_IN_CART: return {...state, checkout: action.payload.checkout} case OPEN_CART: return {...state, isCartOpen: true} case CLOSE_CART: return {...state, isCartOpen: false} default: return state } }

Don’t worry, I’m not going to just post this big reducer and not discuss what is going on; we’ll get to each event! There are a few things to note here.

不用擔(dān)心,我不會(huì)只發(fā)布這個(gè)大型的reducer,而不會(huì)討論正在發(fā)生的事情。 我們將參加每個(gè)活動(dòng)! 這里有幾件事要注意。

We take the initial state from what the state is written as in the Shopify GitHub example and put it in our initState, namely the following four parts of state:

我們從Shopify GitHub示例中編寫(xiě)的狀態(tài)中獲取初始狀態(tài),并將其放入我們的initState ,即狀態(tài)的以下四個(gè)部分:

isCartOpen: false,checkout: { lineItems: [] },products: [],shop: {}

isCartOpen: false, checkout: { lineItems: [] }, products: [], shop: {}

However, in my implementation, I also create a client part of the state. I call the createClient() function once and then immediately set it in the Redux state in index.js . So let’s head into index.js:

但是,在實(shí)現(xiàn)中,我還創(chuàng)建了狀態(tài)的client部分。 我調(diào)用一次createClient()函數(shù),然后立即在index.js中將其設(shè)置為Redux狀態(tài)。 因此,讓我們進(jìn)入index.js :

返回index.js (Back to index.js)

const client = Client.buildClient({ ?storefrontAccessToken: 'your-shopify-token', ?domain: 'your-shopify-url.myshopify.com'});store.dispatch({type: 'CLIENT_CREATED', payload: client});

const client = Client.buildClient({ storefrontAccessToken: 'your-shopify-token', domain: 'your-shopify-url.myshopify.com' }); store.dispatch({type: 'CLIENT_CREATED', payload: client});

In the Shopify buy SDK example, there are a few async calls to get information about the products and store information in React’s componentWillMount() function. That example code looks like this:

在Shopify購(gòu)買(mǎi)SDK示例中,有一些異步調(diào)用來(lái)獲取有關(guān)產(chǎn)品的信息并將信息存儲(chǔ)在React的componentWillMount()函數(shù)中。 該示例代碼如下所示:

componentWillMount() { ? ?this.props.client.checkout.create().then((res) => { ? ? ?this.setState({ ? ? ? ?checkout: res, ? ? ?}); ? ?});this.props.client.product.fetchAll().then((res) => { ? ? ?this.setState({ ? ? ? ?products: res, ? ? ?}); ? ?});this.props.client.shop.fetchInfo().then((res) => { ? ? ?this.setState({ ? ? ? ?shop: res, ? ? ?}); ? ?}); ?}

componentWillMount() { this.props.client.checkout.create().then((res) => { this.setState({ checkout: res, }); });this.props.client.product.fetchAll().then((res) => { this.setState({ products: res, }); });this.props.client.shop.fetchInfo().then((res) => { this.setState({ shop: res, }); }); }

I opted to do that instead as far upstream of a site load as possible, directly in index.js. Then, I issued a corresponding event when each part of the response has been received:

我選擇直接在index.js這樣做,而不是在站點(diǎn)負(fù)載的上游進(jìn)行。 然后,在收到響應(yīng)的每個(gè)部分時(shí),我發(fā)出了一個(gè)相應(yīng)的事件:

// buildClient() is synchronous, so we can call all these after!client.product.fetchAll().then((res) => { ?store.dispatch({type: 'PRODUCTS_FOUND', payload: res});});client.checkout.create().then((res) => { ?store.dispatch({type: 'CHECKOUT_FOUND', payload: res});});client.shop.fetchInfo().then((res) => { ?store.dispatch({type: 'SHOP_FOUND', payload: res});});

// buildClient() is synchronous, so we can call all these after! client.product.fetchAll().then((res) => { store.dispatch({type: 'PRODUCTS_FOUND', payload: res}); }); client.checkout.create().then((res) => { store.dispatch({type: 'CHECKOUT_FOUND', payload: res}); }); client.shop.fetchInfo().then((res) => { store.dispatch({type: 'SHOP_FOUND', payload: res}); });

By now the reducer is created, and the initialization of the Shopify API client is complete all for index.js.

至此,已經(jīng)創(chuàng)建了reducer,并且已經(jīng)針對(duì)index.js完成了Shopify API client的初始化。

回到App.js (Back to App.js)

Now in App.js, wire up Redux’s store to the App state:

現(xiàn)在在App.js ,將Redux的商店連接到App狀態(tài):

import { connect } from 'react-redux';

import { connect } from 'react-redux';

and don’t forget to import the store as well:

并且不要忘記導(dǎo)入商店:

import store from './store';

import store from './store';

At the bottom where export default App should be, modify it to this:

在應(yīng)該export default App的底部, export default App其修改為:

export default connect((state) => state)(App);

export default connect((state) => state)(App);

This connects the Redux state to the App component.

這會(huì)將Redux狀態(tài)連接到App組件。

Now in the render() function we are able to access the Redux’s state with Redux’s getState() (as apposed to using vanilla react’s this.state):

現(xiàn)在,在render()函數(shù)中,我們可以使用Redux的getState()訪問(wèn)Redux的getState()與使用vanilla react的this.state ):

render() { ? ?... ? ? ? ?const state = store.getState();}

render() { ... const state = store.getState(); }

最后:事件處理程序(我們?nèi)栽贏pp.js中) (Finally: the Event Handlers (We’re Still in App.js))

From above, you know that there are only three event handlers that we need in App.js, because the cart uses only three: updateQuantityInCart, removeLineItemInCart, and handleCartClose. The original cart event handlers from the example GitHub repository, which used local component state looked like this:

從上面知道,在App.js中我們只需要三個(gè)事件處理程序,因?yàn)橘?gòu)物車(chē)僅使用三個(gè)事件處理程序: updateQuantityInCart , removeLineItemInCart和handleCartClose 。 示例GitHub存儲(chǔ)庫(kù)中使用本地組件狀態(tài)的原始購(gòu)物車(chē)事件處理程序如下所示:

updateQuantityInCart(lineItemId, quantity) { ?const checkoutId = this.state.checkout.id ?const lineItemsToUpdate = [{id: lineItemId, quantity: parseInt(quantity, 10)}]return this.props.client.checkout.updateLineItems(checkoutId, lineItemsToUpdate).then(res => { ? ?this.setState({ ? ? ?checkout: res, ? ?}); ?});}removeLineItemInCart(lineItemId) { ?const checkoutId = this.state.checkout.idreturn this.props.client.checkout.removeLineItems(checkoutId, [lineItemId]).then(res => { ? ?this.setState({ ? ? ?checkout: res, ? ?}); ?});}handleCartClose() { ?this.setState({ ? ?isCartOpen: false, ?});}

updateQuantityInCart(lineItemId, quantity) { const checkoutId = this.state.checkout.id const lineItemsToUpdate = [{id: lineItemId, quantity: parseInt(quantity, 10)}]return this.props.client.checkout.updateLineItems(checkoutId, lineItemsToUpdate).then(res => { this.setState({ const lineItemsToUpdate = [{id: lineItemId, quantity: parseInt(quantity, 10)}]return this.props.client.checkout.updateLineItems(checkoutId, lineItemsToUpdate).then(res => { this.setState({ checkout: res, }); }); }removeLineItemInCart(lineItemId) { const checkoutId = this.state.checkout.idreturn this.props.client.checkout.removeLineItems(checkoutId, [lineItemId]).then(res => { this.setState({ checkout: res, }); }); }handleCartClose() { this.setState({ isCartOpen: false, }); }

We can refactor them to dispatch events to the Redux store as follows:

我們可以重構(gòu)它們以將事件調(diào)度到Redux存儲(chǔ),如下所示:

updateQuantityInCart(lineItemId, quantity) { ? ?const state = store.getState(); // state from redux store ? ?const checkoutId = state.checkout.id ? ?const lineItemsToUpdate = [{id: lineItemId, quantity: parseInt(quantity, 10)}] ? ?state.client.checkout.updateLineItems(checkoutId, lineItemsToUpdate).then(res => { ? ? ?store.dispatch({type: 'UPDATE_QUANTITY_IN_CART', payload: {checkout: res}}); ? ?});}removeLineItemInCart(lineItemId) { ? ?const state = store.getState(); // state from redux store ? ?const checkoutId = state.checkout.id ? ?state.client.checkout.removeLineItems(checkoutId, [lineItemId]).then(res => { ? ? ?store.dispatch({type: 'REMOVE_LINE_ITEM_IN_CART', payload: {checkout: res}}); ? ?});}handleCartClose() { ? ?store.dispatch({type: 'CLOSE_CART'});}handleCartOpen() { ? ?store.dispatch({type: 'OPEN_CART'});}

updateQuantityInCart(lineItemId, quantity) { const state = store.getState(); // state from redux store const state = store.getState(); // state from redux store const checkoutId = state.checkout.id const state = store.getState(); // state from redux store const checkoutId = state.checkout.id const lineItemsToUpdate = [{id: lineItemId, quantity: parseInt(quantity, 10)}] state.client.checkout.updateLineItems(checkoutId, lineItemsToUpdate).then(res => { store.dispatch({type: 'UPDATE_QUANTITY_IN_CART', payload: {checkout: res}}); }); } removeLineItemInCart(lineItemId) { const state = store.getState(); // state from redux store const state = store.getState(); // state from redux store const checkoutId = state.checkout.id state.client.checkout.removeLineItems(checkoutId, [lineItemId]).then(res => { store.dispatch({type: 'REMOVE_LINE_ITEM_IN_CART', payload: {checkout: res}}); }); } handleCartClose() { store.dispatch({type: 'CLOSE_CART'}); } handleCartOpen() { store.dispatch({type: 'OPEN_CART'}); }

If you were following along, I already mentioned that I added my own handleCartOpen function, because I pass that function down as a prop to my <Nav/> component, so a user is able to open and close the cart from a link in the nav. At a future time, I could move that function to the Nav itself instead of passing it as a prop, since of course the Redux store will also be available there!

如果您一直在學(xué)習(xí),我已經(jīng)提到我添加了自己的handleCartOpen函數(shù),因?yàn)槲覍⒃摵瘮?shù)作為道具傳遞給了<Na v />組件,因此用戶(hù)可以從中的鏈接打開(kāi)和關(guān)閉購(gòu)物車(chē)。導(dǎo)航。 將來(lái),我可以將該功能移至Nav本身,而不是將其作為道具傳遞,因?yàn)楫?dāng)然Redux商店也將在那里可用!

最后添加<Products />組件! (Finally Add that <Products/> Component!)

So, you’ve got a basic store maybe with some simple href’s that link to the corresponding product on your Shopify store? Ha! Get rid of those, and replace them with your brand spankin’ new <Products/> component!

因此,您有一家基本商店,可能帶有一些簡(jiǎn)單的href ,它們鏈接到Shopify商店中的相應(yīng)產(chǎn)品? 哈! 擺脫這些,并用您的品牌spankin'新的<Product s />組件替換它們!

First, import the component into wherever your store markup should be (remember, in my code base I’ve put the shopify example components in a folder called shopify/)

首先,將組件導(dǎo)入您商店標(biāo)記應(yīng)在的任何位置(請(qǐng)記住,在我的代碼庫(kù)中,我已經(jīng)將shopify示例組件放在了一個(gè)名為shopify/的文件夾中)

This will be wherever your products currently are. (In the boilerplate repository I made, I put this in the GenericProductsPage component, to signal that this code could be applied to any page that has a products section):

這將是您當(dāng)前產(chǎn)品的任何位置。 (在我制作的樣板存儲(chǔ)庫(kù)中 ,將其放入GenericProductsPage組件中,以表明該代碼可以應(yīng)用于具有products部分的任何頁(yè)面):

import Products from './shopify/Products';

import Products from './shopify/Products';

Now finally, that past 15–20 minutes of redux boilerplate code edits pays off: we can grab the products part of our state — not by way of vanilla React state passed down over and over again through props — but through grabbing by way of Redux state, in a neat one liner const state = store.getState();:

現(xiàn)在終于可以了,過(guò)去15到20分鐘的redux樣板代碼編輯取得了回報(bào):我們可以獲取狀態(tài)的products部分-而不是通過(guò)props一遍又一遍傳遞的香草React狀態(tài)-而是通過(guò)Redux進(jìn)行獲取狀態(tài),在一個(gè)整潔的線性const state = store.getState();

render () { ? ?const state = store.getState(); // state from redux store ? ?let oProducts = <Products ? ? ?products={state.products} ? ? ?client={state.client} ? ? ?addVariantToCart={this.addVariantToCart} ? ?/>;

render () { const state = store.getState(); // state from redux store const state = store.getState(); // state from redux store let oProducts = <Products products={state.products} client={state.client} addVariantToCart={this.addVariantToCart} />;

Don’t forget to drop the component itself into where it should go in your render() function. For me, that location was buried in Bootstrap style classes and HTML:

不要忘記將組件本身放到render()函數(shù)中應(yīng)該放置的位置。 對(duì)我來(lái)說(shuō),該位置埋在Bootstrap樣式類(lèi)和HTML中:

...<div className="service-content-one"> ? ?<div className="row"> ? ? ? ?<Products/> ? ?</div>{/*/.row*/}</div>{/*/.service-content-one*/}...

... <div className="service-content-one"> <div className="row"> <Products/> </div>{/*/.row*/} </div>{/*/.service-content-one*/} ...

Finally, we will need a single event function addVariantToCart for the cart to work with this products component. Again, for reference, here is the original, vanilla React local state version of addVariantToCart(again, from the shopify example repository):

最后,我們需要一個(gè)事件函數(shù)addVariantToCart ,購(gòu)物車(chē)才能與此產(chǎn)品組件一起使用。 再次,作為參考,這里是addVariantToCart的原始香草React本地state版本(同樣,來(lái)自shopify示例存儲(chǔ)庫(kù)):

addVariantToCart(variantId, quantity){ ?this.setState({ ? ?isCartOpen: true, ?});const lineItemsToAdd = [{variantId, quantity: parseInt(quantity, 10)}] ?const checkoutId = this.state.checkout.idreturn this.props.client.checkout.addLineItems(checkoutId, lineItemsToAdd).then(res => { ? ?this.setState({ ? ? ?checkout: res, ? ?}); ?});}

addVariantToCart(variantId, quantity){ this.setState({ isCartOpen: true, });const lineItemsToAdd = [{variantId, quantity: parseInt(quantity, 10)}] const checkoutId = this.state.checkout.idreturn this.props.client.checkout.addLineItems(checkoutId, lineItemsToAdd).then(res => { this.setState({ checkout: res, }); }); }

and the new, Redux-friendly store.dispatch() version:

以及對(duì)Redux友好的新store.dispatch()版本:

addVariantToCart(variantId, quantity) { ? ?const state = store.getState(); // state from redux store ? ?const lineItemsToAdd = [{variantId, quantity: parseInt(quantity, 10)}] ? ?const checkoutId = state.checkout.id ? ?state.client.checkout.addLineItems(checkoutId, lineItemsToAdd).then(res => { ? ? ?store.dispatch({type: 'ADD_VARIANT_TO_CART', payload: {isCartOpen: true, checkout: res}}); ? ?});}

addVariantToCart(variantId, quantity) { const state = store.getState(); // state from redux store const state = store.getState(); // state from redux store const lineItemsToAdd = [{variantId, quantity: parseInt(quantity, 10)}] const state = store.getState(); // state from redux store const lineItemsToAdd = [{variantId, quantity: parseInt(quantity, 10)}] const checkoutId = state.checkout.id state.client.checkout.addLineItems(checkoutId, lineItemsToAdd).then(res => { store.dispatch({type: 'ADD_VARIANT_TO_CART', payload: {isCartOpen: true, checkout: res}}); }); }

which is of course the one we will use. ?

當(dāng)然,這是我們將要使用的那個(gè)。

Don’t forget to bind it in the constructor:

不要忘記將其綁定到構(gòu)造函數(shù)中:

this.addVariantToCart = this.addVariantToCart.bind(this);

this.addVariantToCart = this.addVariantToCart.bind(this);

Also, you’ll need to connect this component to the store like you did App.js , and import the store:

另外,您需要像將App.js一樣將此組件連接到商店,并導(dǎo)入商店:

import { connect } from 'react-redux'import store from '../store';

import { connect } from 'react-redux' import store from '../store'; import { connect } from 'react-redux' import store from '../store';

at the top, and (assuming the component where you put the Shopify Product component name is GenericProductPage:

在頂部,并且(假設(shè)您將Shopify Product組件放在其中的組件名稱(chēng)為GenericProductPage :

export default connect((state) => state)(GenericProductsPage);

export default connect((state) => state)(GenericProductsPage);

at the bottom.

在底部。

Great! Now, no matter how deeply buried in components, or wherever your products component is declared, it can communicate with the cart’s state!

大! 現(xiàn)在,無(wú)論埋在組件中的深度如何,或者無(wú)論您的產(chǎn)品組件在哪里聲明,它都可以與購(gòu)物車(chē)的狀態(tài)進(jìn)行通信!

最終獎(jiǎng)金示例:標(biāo)題或?qū)Ш街械馁?gòu)物車(chē) (Final BONUS Example: Cart in Your Header or Nav)

If you want to have a ‘Cart’ button in your header / nav, add this button in your Nav component’s render function (again, an example from my current site, which has Bootstrap styles — a very simple version is in the boilerplate example:

如果您想在標(biāo)題/導(dǎo)航欄中添加一個(gè)“購(gòu)物車(chē)”按鈕,請(qǐng)將此按鈕添加到Nav組件的render函數(shù)中(同樣,這是我當(dāng)前站點(diǎn)的示例,該示例具有Bootstrap樣式-一個(gè)非常簡(jiǎn)單的版本在樣例中 :

<div className="App__view-cart-wrapper"><button className="App__view-cart" onClick={this.props.handleCartOpen}> ? ?Cart ? ?</button></div>

<div className="App__view-cart-wrapper"> <button className="App__view-cart" onClick={this.props.handleCartOpen}> Cart </button> </div>

where handleCartOpen is a new handler method you’ll have to add to App.js:

其中handleCartOpen是一個(gè)新的處理程序方法,您必須將其添加到App.js :

constructor() { ?super(); ?... ?this.handleCartOpen = this.handleCartOpen.bind(this); ?...}

constructor() { super(); ... this.handleCartOpen = this.handleCartOpen.bind(this); ... }

in the constructor. Then when you are referencing your Nav component in App.js (or wherever you place your Nav) you pass the function handler:

在構(gòu)造函數(shù)中。 然后,當(dāng)您在App.js中(或您放置Nav的任何地方)引用Nav組件時(shí),您將傳遞函數(shù)處理程序:

<Nav handleCartOpen={this.handleCartOpen}/>

<Nav handleCartOpen={this.handleCartOpen}/>

This could also be refactored to an event in Redux, but since it was only one child down, I did it the vanilla React way.

也可以將其重構(gòu)為Redux中的一個(gè)事件,但是由于只有一個(gè)孩子,我采用了香草的React方法。

樣式組件 (Styling Component(s))

I relied on Shopify’s CSS file, app.css, located in the shared/ folder in the storefront-api-example repository (you can’t miss it, it’s the only file in shared/ )!

我依靠ShopifyCSS文件app.css ,該文件位于storefront-api-example存儲(chǔ)庫(kù)的shared/文件夾中(您不能錯(cuò)過(guò)它,它是shared/唯一的文件)!

Make sure to copy that into your styles/ folder or wherever it needs to be and include it in your index.js file. In my index.js it looks like this:

確保將其復(fù)制到您的styles/文件夾中或需要復(fù)制的任何位置,并將其包含在index.js文件中。 在我的index.js它看起來(lái)像這樣:

import './styles/shopify.css';

import './styles/shopify.css';

Since I renamed the app.css which was in the Shopify example repository to shopify.css , and put it folder styles. This convention is also used in the boilerplate repository code.

由于我改名為app.css這是在Shopify例如存儲(chǔ)庫(kù)shopify.css ,并把它的文件夾styles 。 在樣板存儲(chǔ)庫(kù)代碼中也使用此約定。

From here it’s pretty easy to identify where exactly in shopify.css the default bright blue color for the buttons is defined, and so on. I’m going to save detailed CSS customization for you to handle. ?

從這里很容易確定在shopify.css中確切的shopify.css ,為按鈕定義了默認(rèn)的亮藍(lán)色,依此類(lèi)推。 我將保存詳細(xì)CSS定制供您處理。

But who knows, maybe I’ll post on that eventually — but I find the styles from Shopify pretty good and easy enough to modify.

但是誰(shuí)知道呢,也許我最終會(huì)在此發(fā)布—但是我發(fā)現(xiàn)Shopify中的樣式非常好并且很容易修改。

外賣(mài) (Takeaways)

In my opinion, this is a perfect (non-todo list ?) use of Redux. Redux cleanly organizes the event functions and state of the Shopify cart and makes it easy to access the cart’s state from any other component. This is much easier to maintain than passing pieces of state to children and using multiple event handlers to pass events back up to parent functions all over a React app.

我認(rèn)為,這是Redux的完美用法(非待辦事項(xiàng)列表?)。 Redux干凈利落地組織了Shopify購(gòu)物車(chē)的事件功能和狀態(tài),并使其易于從任何其他組件訪問(wèn)購(gòu)物車(chē)的狀態(tài)。 這比將狀態(tài)傳遞給子級(jí)并使用多個(gè)事件處理程序?qū)⑹录鬟f回整個(gè)React應(yīng)用程序的父函數(shù)要容易得多。

As shown as an example in the tutorial, the cart’s state is accessed easily in the Nav component and the shop section of the front page. I’ll also be able to easily add it to a sort of ‘featured’ product section as well, once Siren Apparel is ready for that.

如本教程中的示例所示,可以在Nav組件和首頁(yè)的shop部分中輕松訪問(wèn)購(gòu)物車(chē)的狀態(tài)。 一旦Siren Apparel做好了準(zhǔn)備,我還可以輕松地將其添加到“特色”產(chǎn)品部分中。

查找代碼 (Find the Code)

A boilerplate repository of this implementation can be found here. It is a near blank create-react-app app, but with all the changes of this tutorial implemented in index.js and App.js , as well as a super basic GenericStorePage and Nav components.

可在此處找到此實(shí)現(xiàn)的樣板存儲(chǔ)庫(kù)。 這是一個(gè)幾乎空白的create-react-app程序,但是本教程的所有更改都在index.js和App.js ,以及超基本的GenericStorePage和Nav組件。

I built the code on the repo while re-reading and updating my own tutorial here, to make sure this tutorial makes sense!

在重新閱讀和更新自己的教程時(shí),我在倉(cāng)庫(kù)上構(gòu)建了代碼,以確保該教程有意義!

Because I am crazy ?, Siren Apparel’s website is all open-sourced. So if you want to fool around with my implementation, check out the repository!

因?yàn)槲爷偭?#xff1f;,Siren Apparel的網(wǎng)站全部開(kāi)源。 因此,如果您想閑逛我的實(shí)現(xiàn),請(qǐng)刪除存儲(chǔ)庫(kù)!

I hope you enjoyed this tutorial! If anything isn’t clear or just plain not working, let me know! I’ll try to assist you!

希望您喜歡本教程! 如果有任何不清楚的地方,或者只是無(wú)法正常工作,請(qǐng)通知我! 我會(huì)盡力為您服務(wù)!

Thanks to Lisa Catalano at CSS-Snippets for the simple Nav example which I used in the boilerplate repository!

感謝CSS-Snippets的Lisa Catalano提供了我在樣板存儲(chǔ)庫(kù)中使用的簡(jiǎn)單Nav示例 !

Cheers! ?

干杯!

Chris

克里斯

翻譯自: https://www.freecodecamp.org/news/a-detailed-tutorial-how-to-use-shopifys-storefront-api-with-react-and-redux-37f95cbab7f/

shopify二次開(kāi)發(fā)教程

總結(jié)

以上是生活随笔為你收集整理的shopify二次开发教程_详细教程:如何将Shopify的Storefront API与React和Redux结合使用...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

中文字幕 成人 | 91最新在线视频 | 欧美另类交在线观看 | 中文在线资源 | 国产亚州av | 国产在线精品二区 | 91伊人影院 | 日本激情中文字幕 | 蜜桃av久久久亚洲精品 | 久草在线网址 | 久久国产一二区 | 国产97av | 99热国产精品 | 一区 二区电影免费在线观看 | 手机av电影在线 | 久久蜜臀av | 一级黄色免费网站 | 国产午夜在线观看 | www.日本色 | 亚洲婷婷丁香 | 五月婷婷影视 | 色多多污污在线观看 | 日本精品在线视频 | 日本视频网 | av片免费播放| 久久久久久国产一区二区三区 | 久久综合成人网 | 在线观看视频一区二区三区 | 成人国产精品一区 | 日韩免费小视频 | 国产精品自产拍在线观看网站 | 欧美综合在线视频 | 国产一级高清视频 | 人人插人人看 | 91精品成人| 在线视频观看91 | 久久高清毛片 | 国产97超碰| 综合久久久久久久 | 国产精品毛片 | 亚洲国产99 | 日韩精品视频在线免费观看 | 久久久精选 | 探花在线观看 | 美女网站免费福利视频 | 麻豆免费看片 | av成人在线看 | 精品v亚洲v欧美v高清v | 一区二区三区动漫 | 九月婷婷人人澡人人添人人爽 | 久久久久黄色 | 国产a免费| 碰天天操天天 | 91网页版免费观看 | 精品欧美在线视频 | 亚洲伦理一区二区 | 国产精品免费麻豆入口 | 日本中文字幕在线播放 | 亚洲精品网址在线观看 | 久久草草影视免费网 | 亚洲欧美日本国产 | 免费亚洲视频在线观看 | 国产一区二区手机在线观看 | 美女久久久久久久久久 | 在线天堂日本 | 久久精品理论 | 国产九九热| 岛国av在线免费 | 91黄色免费看 | av看片在线 | 中文字幕亚洲欧美日韩 | 日本成人中文字幕在线观看 | 国产精品自产拍在线观看蜜 | 日韩精品免费在线观看 | 久久久午夜剧场 | 免费观看国产视频 | 免费视频黄色 | 欧美成人视 | 婷婷六月久久 | 亚洲一区二区观看 | 免费黄色av电影 | 白丝av在线 | av在线免费观看网站 | 中文字幕永久免费 | 九色精品免费永久在线 | 人人天天夜夜 | 婷婷综合五月天 | 婷婷成人亚洲综合国产xv88 | 一区二区三区免费看 | 一区二区理论片 | 六月激情婷婷 | 99高清视频有精品视频 | 国产精品久久久久久久久大全 | 久久久久久久久久久影院 | www久久久久 | 天天色天天干天天色 | 亚洲禁18久人片 | 6080yy精品一区二区三区 | 狠狠操狠狠干天天操 | 亚洲黄色一级视频 | 亚洲资源在线 | 99久久超碰中文字幕伊人 | 99爱这里只有精品 | av一级二级 | 国产录像在线观看 | 亚洲亚洲精品在线观看 | 99视频在线观看一区三区 | 九九三级毛片 | 久草观看视频 | 亚洲激情 在线 | 亚洲第一区在线观看 | 九九久久久| 日本三级在线观看中文字 | 久久99久久久久久 | 久久久久久久久久久高潮一区二区 | 狠狠操在线| 欧美a级在线 | 欧美黄在线 | 狠狠综合久久 | 久久激情久久 | 日韩精品中文字幕在线不卡尤物 | 成人理论电影 | 最近日本字幕mv免费观看在线 | 97国产视频 | 免费涩涩网站 | 日本午夜在线亚洲.国产 | 精品国产99国产精品 | 色综合久久久久久中文网 | 欧美日韩一区二区三区视频 | 久久精品中文字幕一区二区三区 | 免费毛片一区二区三区久久久 | 亚洲国产精品久久久 | 午夜精品久久久久久久99热影院 | 久草线| 精品视频免费观看 | 中文字幕 影院 | 亚洲精品男人天堂 | 欧美日韩国内在线 | 久久综合亚洲鲁鲁五月久久 | 黄色一级在线视频 | 亚洲三级性片 | 在线黄av | 97国产情侣爱久久免费观看 | 波多野结衣视频一区二区 | 欧美激情h | 毛片网站在线看 | 91精品国产九九九久久久亚洲 | 天天艹天天操 | 玖草在线观看 | 国产伦精品一区二区三区在线 | 久久精品国产精品亚洲 | www.成人sex| 国产一区二区高清视频 | 亚洲高清视频在线观看免费 | 片网站| 国产精品久久久久一区二区国产 | 91最新在线 | 日韩精品一区二区在线观看 | 99热这里只有精品1 av中文字幕日韩 | 狠狠操狠狠干2017 | 黄色av电影免费观看 | 免费日韩在线 | 黄污网站在线观看 | 91人人揉日日捏人人看 | 波多野结衣在线观看一区二区三区 | 成人中文字幕在线 | 精品一区二区免费视频 | 中文字幕在线观看播放 | av一区二区在线观看中文字幕 | 国产精品久久久久久一二三四五 | 九九色在线 | 亚洲精品午夜aaa久久久 | 高清一区二区三区 | 免费在线观看av网站 | 狠狠干狠狠操 | 婷婷综合伊人 | 亚洲欧洲精品一区二区精品久久久 | 4hu视频 | 超碰在线色 | 天天色天天 | 日日干视频 | 国产精品色婷婷视频 | 一区二区三区免费网站 | 丁香视频五月 | 国产在线专区 | 在线视频免费观看 | 国产成人精品亚洲日本在线观看 | 91看片看淫黄大片 | 久久免费黄色网址 | 国产小视频在线免费观看视频 | 国语麻豆| 国产成人一区二区三区影院在线 | 国产精品一区二区久久 | 中文字幕精品在线 | 麻豆视频成人 | 在线观看免费视频 | 久久国产精品久久国产精品 | 国产精品久久一区二区三区, | 精品三级av | 欧美精品中文字幕亚洲专区 | 日韩免费电影 | 国产护士hd高朝护士1 | 2000xxx影视 | 97色资源| 国产涩涩在线观看 | 成人免费在线视频 | 91九色视频在线播放 | 91精品在线免费视频 | av大片免费 | 日日操日日干 | 国产二级视频 | 国产又粗又猛又爽 | 黄色成人影视 | 亚洲免费在线观看视频 | 深爱五月网 | 人人擦 | 国产精品黄色在线观看 | 欧美激情精品久久久久久变态 | 99精品免费久久久久久日本 | 久久精品国产一区二区电影 | 亚洲欧美国产日韩在线观看 | 久操免费视频 | 国产亚洲高清视频 | 欧美一区二区三区免费观看 | 免费在线成人 | 白丝av免费观看 | 久艹视频免费观看 | 天天操天天干天天插 | 色综合久久久久久久久五月 | 婷婷五月在线视频 | 天天做日日爱夜夜爽 | 久久久久久久久久网 | 国产成人福利在线 | 日本在线观看中文字幕 | 超碰精品在线 | 精品在线不卡 | 日韩电影中文,亚洲精品乱码 | 日日天天狠狠 | 天天干国产| 天天在线免费视频 | 综合色狠狠 | 亚洲视频久久久 | 97在线免费观看 | 91新人在线观看 | 国产福利精品在线观看 | 97超碰中文字幕 | 天天操天天干天天干 | 狠狠干婷婷 | 国产精品ssss在线亚洲 | 午夜a区| 色综合久久精品 | 国产精品18久久久久久久久久久久 | 精品久久美女 | 精品一二三区视频 | 国产在线a不卡 | 中文字幕 欧美性 | 免费观看十分钟 | 97精品免费视频 | 夜夜摸夜夜爽 | 婷婷国产v亚洲v欧美久久 | 色91av| 国产精品黑丝在线观看 | 午夜av一区二区三区 | 亚洲国产中文字幕在线观看 | 日韩在线不卡视频 | 在线黄频| 国产午夜精品久久久久久久久久 | 黄网站色视频 | 奇米网777 | 欧美a视频在线观看 | 久久在视频 | 欧美性直播 | 欧美精品久久久久久久久久 | 欧美激情综合色综合啪啪五月 | 五月婷婷影院 | 国产成人不卡 | 懂色av懂色av粉嫩av分享吧 | 国产精品精品久久久 | 久久精品99国产 | 日韩精品五月天 | 视频福利在线 | 国产在线不卡精品 | 亚洲成人av电影在线 | 日韩色av色资源 | av一二三区| 日韩精品视频免费看 | 在线观看你懂的网址 | 成人免费观看完整版电影 | 国产成人免费在线 | 九九九九免费视频 | 黄a在线 | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 国产护士hd高朝护士1 | 精品国产欧美一区二区三区不卡 | 欧美天天射 | 伊人狠狠 | 欧美少妇bbwhd | 亚洲视频一区二区三区在线观看 | 精品a在线| 国产999免费视频 | 天天操夜夜叫 | 91在线www| 欧美一区免费在线观看 | 亚洲欧洲精品一区二区 | 国产精品精品国产色婷婷 | 免费在线观看av的网站 | 中文字幕在线观看亚洲 | 国产偷在线| 欧美成人在线网站 | 永久免费精品视频 | 99精品久久久 | 免费av在线播放 | 欧美三级免费 | 国产成年人av | 中文字幕日韩精品有码视频 | 久久精品国产一区二区 | 国产在线观看av | 久操视频在线免费看 | 888av| 香蕉网站在线观看 | 国产免费美女 | 久久久久女教师免费一区 | 国产精品理论片在线观看 | 欧美日韩亚洲在线观看 | 精久久久久| 免费在线色电影 | 美女黄视频免费 | 蜜臀av免费一区二区三区 | 国产在线观看99 | 天天色天天综合网 | 在线观看免费版高清版 | 国产黄| 久久精品香蕉 | 欧美极品裸体 | 91亚洲国产成人久久精品网站 | 日本公妇在线观看 | 婷婷网在线| 热久久视久久精品18亚洲精品 | 丁香伊人网 | 丝袜足交在线 | 日韩电影在线视频 | 99色网站 | 天天操天天玩 | 日韩在线观看视频网站 | 日本乱码在线 | 久久久久久久久久久久国产精品 | 亚洲精品九九 | 亚洲午夜久久久综合37日本 | 中文字幕在线播放第一页 | 在线观看视频三级 | av在线免费观看黄 | 久99久中文字幕在线 | 色婷婷六月 | 玖玖爱国产在线 | 精品国产免费久久 | 亚洲日本va午夜在线电影 | 久久激五月天综合精品 | 色综合久久综合网 | 亚洲精品国产精品国自产在线 | 天天操天天综合网 | 射久久 | 国产精品国产自产拍高清av | 在线影视 一区 二区 三区 | 久久伦理视频 | 久久久久久久久久网站 | 久久久久网址 | 亚洲精品乱码白浆高清久久久久久 | av黄色免费网站 | 久久视频精品 | 在线观看视频 | 日韩av中文 | va视频在线 | 丁香六月网 | 亚洲免费在线观看视频 | 国产精品久久久久久99 | 国产做a爱一级久久 | 中文视频一区二区 | 日本在线视频一区二区三区 | 91精品福利在线 | 国产精品久久久久久久av大片 | www.狠狠操.com | 黄色字幕网 | 国产黄色在线看 | 欧美精品久久久久 | 亚洲国产剧情av | 久久综合久色欧美综合狠狠 | 欧美另类巨大 | 青青草华人在线视频 | 毛片一区二区 | 久久久久中文 | 人人搞人人爽 | 亚洲激情五月 | 天天干天天操天天干 | 美女国产在线 | 国产区久久 | 视频在线观看99 | 狠狠操天天操 | 亚洲视频2 | 最近免费中文字幕mv在线视频3 | 免费av看片| 欧美最猛性xxxxx免费 | 亚洲精品国产第一综合99久久 | aaa亚洲精品一二三区 | 久久激情视频 久久 | 久久精品香蕉视频 | 一区二区视频免费在线观看 | 91精品在线免费观看 | 日韩高清国产精品 | av在线8 | 深夜成人av| 国产在线视频资源 | 久久在线精品 | 久亚洲| 国产短视频在线播放 | 国产成人一区二区啪在线观看 | 久久99久久99精品免视看婷婷 | 99re6热在线精品视频 | 91av播放| 免费激情网 | 搡bbbb搡bbb视频| 天天干婷婷 | 日韩欧美大片免费观看 | 久久黄页 | adn—256中文在线观看 | 粉嫩av一区二区三区四区五区 | 国产视频 亚洲视频 | 国产在线精品一区二区 | 91在线免费视频 | 黄色av三级在线 | 玖草在线观看 | 免费看久久 | www五月| 免费成人在线视频网站 | 欧美,日韩 | 日韩av一区二区三区在线观看 | 亚洲精品视频免费在线 | 日韩在线观看 | 精品久久久久久亚洲综合网 | 亚洲视频综合 | 婷婷六月久久 | 欧美中文字幕久久 | 国产精品久久电影观看 | 在线99视频| 在线观看免费视频 | 91视频-88av | a√天堂中文在线 | 日韩av男人的天堂 | 99999精品| 中文字幕人成人 | 欧美日韩色婷婷 | 精品国产一区二区三区久久影院 | 久久99精品视频 | 亚洲一区二区三区精品在线观看 | 日韩av资源在线观看 | 最近2019年日本中文免费字幕 | 最新超碰在线 | 天天干天天做天天操 | 精品在线视频一区 | 国产在线2020 | 久久蜜臀一区二区三区av | 国产一二区免费视频 | 狠狠色2019综合网 | 五月的婷婷| av电影在线不卡 | 久草视频中文在线 | 日韩高清在线一区二区 | 婷婷丁香五 | 亚洲电影院 | 国产成人av片 | 中文字幕免费国产精品 | 欧美韩国日本在线观看 | 超碰成人免费电影 | 欧美日韩一区久久 | 免费看黄在线 | 操操操天天操 | 丁香六月色 | 奇米影视在线99精品 | 国产日女人 | 亚洲精品中文在线 | 一级特黄aaa大片在线观看 | 久久99精品一区二区三区三区 | 国产偷v国产偷∨精品视频 在线草 | 日本久久高清视频 | 亚洲激情校园春色 | 黄色毛片在线看 | 国产一区二区精品91 | 成人av网站在线播放 | 日韩理论片在线 | 国产在线色站 | 日韩精品第1页 | 国产玖玖视频 | 天天爽夜夜爽人人爽一区二区 | 欧美视频在线观看免费网址 | 91在线视频精品 | 天天色天天射综合网 | 久99久精品 | 久久综合久久八八 | 欧美做受高潮电影o | 一级性视频 | 99视频在线观看一区三区 | 日韩精品久久久免费观看夜色 | 日韩中文字幕a | 日韩精品一区二区三区在线播放 | 久久不色 | 亚洲黄色免费 | 不卡av在线 | 国产精品不卡在线观看 | 欧美国产三区 | 五月天综合激情 | 久久精品国产一区二区电影 | 日韩欧美在线观看一区二区 | 特级毛片网 | 二区视频在线观看 | 美女精品 | 99色免费视频 | 成年人国产在线观看 | 天天操天天摸天天射 | 中文字幕一区二区三区乱码不卡 | 精品久久久久久久久中文字幕 | 91精品小视频| 亚洲视频axxx | 久久成人麻豆午夜电影 | 中文字幕视频在线播放 | 亚洲另类在线视频 | 国产亚洲情侣一区二区无 | 久久久美女 | 日本特黄一级 | 久久综合色综合88 | 操夜夜操 | 国产在线免费观看 | 久久嗨| 中文字幕永久在线 | 97在线看 | 欧洲一区二区在线观看 | 蜜臀久久99静品久久久久久 | 18久久久久久 | 天天射天天射天天 | 不卡中文字幕在线 | 国产原创91 | 日韩极品视频在线观看 | 日韩精品视频免费看 | 亚州av一区| 制服丝袜亚洲 | 亚洲精品乱码久久久久久久久久 | 精品国产区在线 | 免费看片网页 | 免费在线观看一级片 | 天堂久久电影网 | 久久免费美女视频 | 亚洲伦理一区二区 | 天堂久久电影网 | 欧美日韩国产综合网 | av大全在线观看 | 欧美韩日在线 | 欧美a级在线播放 | 欧美日韩午夜 | 国产在线精品国自产拍影院 | 久久精品人| 精品三级av| 精品久久一| 中文字幕激情 | 亚洲春色奇米影视 | av三级av | 欧美日韩视频一区二区 | 成人欧美一区二区三区黑人麻豆 | 91网页版在线观看 | 欧美大片第1页 | 美女网站视频免费都是黄 | 很黄很黄的网站免费的 | 蜜臀av性久久久久av蜜臀三区 | 美女久久精品 | 激情丁香综合五月 | 国产成人精品一区二区在线观看 | 午夜精品影院 | 日本在线中文在线 | 国产一区二区手机在线观看 | 中文有码在线视频 | 久久精品99国产国产 | 久草在| 国产一区免费视频 | 久久午夜国产精品 | 国产91综合一区在线观看 | 久久久久人人 | 99热手机在线 | 日韩午夜在线观看 | 在线观看中文字幕亚洲 | 欧美精品在线视频 | 精品久久久久一区二区国产 | 国产精品久久久久久久久久不蜜月 | 天天操天天爱天天爽 | 特级片免费看 | 不卡视频在线看 | 国产日本高清 | 日韩av一区二区三区四区 | 国产精品免费一区二区三区在线观看 | 亚洲国产精选 | 久草91视频 | 精品99视频 | 久久精品一二三区 | 一性一交视频 | 黄色资源在线 | 97免费在线观看视频 | 日韩中文在线视频 | 欧美一级日韩三级 | 欧美久久电影 | 欧美高清视频不卡网 | 日韩毛片在线一区二区毛片 | 精品网站999www | 中文字幕亚洲欧美 | 三级黄免费看 | 人人爽人人澡 | 免费的黄色的网站 | 在线亚洲日本 | 成人毛片网 | 亚洲四虎影院 | 色九九视频 | 欧美日韩另类视频 | 久久私人影院 | 欧美成年黄网站色视频 | 中文亚洲欧美日韩 | 久久伊人八月婷婷综合激情 | 亚洲乱码久久 | 五月在线视频 | 久久九九视频 | 欧美日本不卡高清 | 国产1区在线观看 | 国精产品满18岁在线 | 久久夜色精品国产亚洲aⅴ 91chinesexxx | 日韩色综合 | 婷婷久久一区 | 亚洲一区免费在线 | 天天操福利视频 | 欧美日韩久久一区 | 久久久三级视频 | 国产成人久久精品77777综合 | 日本性高潮视频 | 国产精品九九九九九 | 久久99这里只有精品 | 69久久夜色精品国产69 | 四虎永久精品在线 | 欧美精品久久久久久 | 日韩激情中文字幕 | 精品一二三四五区 | 久久精品伊人 | 久久国产系列 | 九九热在线播放 | 久久99精品国产 | 久草影视在线观看 | 久久精精品| 91麻豆文化传媒在线观看 | 亚洲91在线| 成人免费视频免费观看 | 久久精品视频在线播放 | 久久精品久久国产 | 在线 你懂 | 99看视频在线观看 | 亚洲第一av在线播放 | 91视频在线免费下载 | 亚洲va综合va国产va中文 | 菠萝菠萝在线精品视频 | 久久一及片 | 超碰99人人 | 91夜夜夜 | 久久免费视频在线 | 久久久久亚洲精品国产 | 久久国产精品影视 | 伊人永久| 国产成人久久精品 | 欧美一区二区三区激情视频 | 免费高清在线观看成人 | 欧美成人久久 | 亚洲电影自拍 | 天天天综合 | 婷婷午夜激情 | 国产精品久久99综合免费观看尤物 | www.久久成人 | 三上悠亚一区二区在线观看 | 色网站国产精品 | 国产精品美女免费视频 | 日韩精品久久久久久久电影99爱 | 国产96在线观看 | 五月婷婷综合激情 | 欧美精品色| 久久在现| 久久久久久国产一区二区三区 | 国产一级视频在线观看 | 视频高清 | 六月丁香激情综合色啪小说 | 五月综合婷 | 亚洲黄色高清 | 亚洲人成人在线 | 成人午夜在线电影 | 婷婷在线网 | 中文av字幕在线观看 | 中文字幕在线视频国产 | av黄色av| 亚洲一区网| 韩国一区二区三区在线观看 | 久久久久久久久黄色 | 91免费高清| 欧美日韩高清在线一区 | 久久久久国产精品www | 亚洲人人爱 | 久久午夜精品视频 | 97在线看片 | 国产精品igao视频网入口 | 欧美精品亚洲精品 | 精品国产1区 | 国内久久看 | 午夜在线国产 | 99色视频 | av电影在线观看 | 午夜精品一区二区三区在线观看 | 一级a性色生活片久久毛片波多野 | 国产麻豆剧果冻传媒视频播放量 | 蜜臀一区二区三区精品免费视频 | 国产99久久久精品 | 中文字幕在线观看网址 | 久久婷婷激情 | 精品国产免费看 | 又黄又刺激的视频 | 美国av片在线观看 | 久久成人精品视频 | 免费在线观看的av网站 | 天天射天天拍 | 毛片激情永久免费 | 黄色亚洲 | 精品国产一区二区三区久久影院 | 狠狠干在线播放 | 久久夜夜夜 | 黄色大片国产 | 亚洲高清视频在线 | 美女视频一区二区 | 欧美精品日韩 | www.在线看片.com | 一区二区中文字幕在线观看 | 国产成人99av超碰超爽 | 日韩久久精品一区 | 久章操 | 久热久草| 久久久久久久久久久成人 | 制服丝袜在线91 | 97热在线观看 | 国产美女在线观看 | 丝袜美腿av | 成人免费观看网址 | 天天色天天射天天干 | 国产精品视频999 | 亚洲欧洲av在线 | 久久久久99精品国产片 | 久久视屏网 | 婷婷色社区| 欧美国产一区在线 | 麻豆影视网 | 久久久久久久久久久久亚洲 | 国产一区久久久 | 亚洲少妇影院 | 九九国产精品视频 | 右手影院亚洲欧美 | 成年人国产精品 | 精品在线一区二区三区 | 久久国产精品久久w女人spa | 少妇搡bbbb搡bbb搡69 | 激情视频免费观看 | 亚洲一区美女视频在线观看免费 | 久久伦理影院 | 天天色天天操天天爽 | 久久视频国产精品免费视频在线 | 国产专区视频在线 | 欧美另类交人妖 | 一区在线免费观看 | 91在线小视频 | 久久久午夜剧场 | 夜夜夜夜爽 | 91黄色小网站 | 日免费视频 | 在线你懂| 日本午夜在线观看 | 国产精品成人aaaaa网站 | 午夜少妇| av高清网站在线观看 | 久久国产免费 | 成年人av在线播放 | 国产一级二级在线 | 久久久久亚洲最大xxxx | 久久麻豆精品 | 粉嫩av一区二区三区免费 | 黄色aa久久| 911在线| 国产黑丝袜在线 | 久久久黄色av | 久久久久久不卡 | 操操碰| 五月婷网站 | 国内精品久久天天躁人人爽 | www.色国产| 久久曰视频| av久久在线 | 久久五月婷婷丁香社区 | 日日夜夜精品视频 | 99热官网| 色先锋资源网 | 国产成人免费在线 | 免费日韩一区二区 | 天天久久综合 | 久久亚洲影视 | 九九交易行官网 | 精品国产自在精品国产精野外直播 | 天堂av观看| 欧美激情精品久久久久久免费印度 | 色99之美女主播在线视频 | 婷婷色综合色 | 亚洲一区二区三区毛片 | 不卡中文字幕av | 亚洲精品麻豆 | 中文字幕 第二区 | 一区二区观看 | 不卡国产视频 | 日操干| 国产精品一区二区吃奶在线观看 | 国产日韩视频在线播放 | 97精产国品一二三产区在线 | 国产亚洲婷婷免费 | 国产免费三级在线观看 | 91激情视频在线观看 | 中文字幕第一页在线视频 | 国产精品涩涩屋www在线观看 | 国产精品一区二区精品视频免费看 | 在线午夜av | 九九久久影视 | 国产夫妻自拍av | 天海冀一区二区三区 | 91视频麻豆 | 国产精品视频永久免费播放 | 97精品国产97久久久久久免费 | 亚洲欧美少妇 | 国产69久久久 | 国产在线视频一区二区三区 | 欧洲亚洲女同hd | 天天在线免费视频 | 特黄免费av| 精品国产一区二区三区免费 | 免费国产ww | 成人四虎 | 婷婷视频在线观看 | 婷婷丁香五 | 中文在线天堂资源 | 国产伦精品一区二区三区免费 | 久久精品亚洲精品国产欧美 | 成人av资源网站 | 91少妇精拍在线播放 | 手机看片国产 | 永久免费观看视频 | 中文字幕你懂的 | 国产精品一区二区在线播放 | 婷婷色网视频在线播放 | 日本在线观看中文字幕无线观看 | 特级毛片在线免费观看 | 97日日 | 久久久久久久久福利 | 四虎www. | 久久午夜电影院 | 日韩免费在线观看网站 | 日韩在线高清免费视频 | 国产福利91精品一区 | 91人人爱 | 亚洲精品在线观看中文字幕 | 精品一区二区免费 | 久久久久久久久久免费 | 亚洲日本成人网 | 日日夜夜综合 | 国产一区二区三区网站 | 久久九九视频 | 亚洲欧美日韩国产精品一区午夜 | 国产中文在线播放 | 久久深夜福利免费观看 | 久久亚洲欧美 | 日本精品视频在线播放 | 午夜国产一区二区三区四区 | 欧美性一级观看 | 特级西西444www高清大视频 | 91热爆在线观看 | av免费在线看网站 | 丁香电影小说免费视频观看 | 91九色在线观看 | 色视频国产直接看 | 国产日产欧美在线观看 | 免费黄色网址大全 | 亚洲三级毛片 | 91av官网 | 日韩午夜电影院 | 日韩在线观看视频一区二区三区 | 日韩r级电影在线观看 | 黄在线免费看 | 久久视频这里有久久精品视频11 | 99中文字幕在线观看 | 精品国产区 | 成 人 黄 色 视频 免费观看 | 国产群p视频 | 91在线九色 | 精品国产一区二区三区男人吃奶 | 亚洲精品动漫成人3d无尽在线 | 91在线免费看片 | 91精品综合在线观看 | 久久成电影| 日韩av视屏在线观看 | 91精品视频免费 | 91在线观| 色www.| 国产日韩精品在线观看 | 国产精品美女久久久久久久 | 中文字幕第一页在线vr | 亚洲 欧美 变态 国产 另类 | 婷婷 综合 色 | 久久久久久久国产精品影院 | 国产一级免费观看视频 | 欧美在线视频不卡 | 国产精品福利小视频 | 精品专区 | 激情久久久久久久久久久久久久久久 | 五月婷激情 | 福利精品在线 | 国产专区精品 | wwxxxx日本| 精品视频资源站 | 国产第一页精品 | 欧美色黄| 国产精品一区免费观看 | 亚洲国产中文字幕 | 美女视频久久 | 日韩精品久久一区二区三区 | 成人超碰在线 | 日日夜夜免费精品视频 | 日韩网站免费观看 | 97在线免费观看 | 色www免费视频| 亚洲精品麻豆 | 99九九99九九九视频精品 | 久久久www成人免费毛片麻豆 | 久久免费看片 | 色婷婷综合久久久久 | 又色又爽又激情的59视频 | 天天综合网在线观看 | 国产成人在线观看 | 亚洲精品视频一二三 | 在线观看成人福利 | 在线免费观看麻豆 | 久久好看 | 国产精品一二 | 日本久久91 | 精品国产一区二区三区四区在线观看 | 成人黄色在线观看视频 | 久久天天躁| 黄色大全免费网站 | 久久99国产一区二区三区 | 国产精品一区二区三区在线 | 日韩一区正在播放 | 国产在线精品福利 | 久久综合狠狠 | 日精品在线观看 | av一级久久| 在线观看不卡的av | 日韩xxxbbb | 久久综合九色综合欧美狠狠 | 色综合久久88| 99精品在线免费 | 黄网站免费久久 | 国产激情小视频在线观看 | 亚洲国产精品视频在线观看 | 一区二区三区中文字幕在线观看 | 人人爱人人做人人爽 | 日韩免费观看一区二区三区 | 91网站在线视频 | 国产你懂的在线 | 日本久久精品视频 | 成人久久18免费网站 | 二区三区毛片 | 久久社区视频 | 精品视频97 | 最近日本字幕mv免费观看在线 | 色瓜| 久久亚洲福利视频 | 国产成人三级在线播放 | 啪啪肉肉污av国网站 | 国产中文字幕在线免费观看 | 精品免费观看视频 | 久久99久久精品国产 | 在线视频成人 | 中文字幕在线一区二区三区 | 久久精品综合 | 视频二区在线 | 国产日韩欧美在线影视 | 国产精品久久久久一区二区三区共 | h视频日本 | 亚洲欧美精品一区二区 | 欧美ⅹxxxxxx | 天天干天天摸天天操 | 99精品免费|