JayLow Posted August 2, 2021 Share Posted August 2, 2021 Hi All, Looking for some advice on this. First, here is a codesandbox link that is a minimal demo of my issue. https://codesandbox.io/s/sad-dirac-p04pv?file=/src/components/textSpan.vue Let me try to explain. The textSanitizer component serves as a serializer for a WYSIWYG from a CMS. Every type of text has its own respective component to render that type of text (heading, paragraph, textSpan, etc). These each have their own unique animations, which I call using refs in the mounted hook. What I would like to accomplish, is have all of these linked together to stagger on one scroll trigger, as opposed to each having its own. That way when someone scrolls to a text block, they cant solely trigger the first element without triggering the rest. I was thinking this would involve setting up a timeline on the textSanitizer component, and having each child append itself once it renders? Not sure if this is the right path, but just an idea Link to comment Share on other sites More sharing options...
OSUblake Posted August 2, 2021 Share Posted August 2, 2021 Maybe this thread can give you some ideas. Link to comment Share on other sites More sharing options...
OSUblake Posted August 2, 2021 Share Posted August 2, 2021 Another option would be to build your animation in a parent component. You can use GSAP's selector utility to grab the elements you need. mounted() { const q = gsap.utils.selector(this.$el); gsap.timeline({ ... }) .to(q(".foo"), { ... }) } 1 Link to comment Share on other sites More sharing options...
OSUblake Posted August 2, 2021 Share Posted August 2, 2021 Another option would be to use refs with your components. That will allow you to access the instance of your component. <MyComponent ref="someRef"></MyComponent> https://codesandbox.io/s/sad-wilson-7yvy4?file=/src/App.vue cc @Cassie This is kind of like forwardRef in React. Link to comment Share on other sites More sharing options...
JayLow Posted August 3, 2021 Author Share Posted August 3, 2021 @OSUblake Selector utility looks promising. Docs say React and Angular refs though. Is it setup to work with Vue? I've believe I've tried the second option, but I've had cases where it will try to access the ref before it is defined. I might try an emit where the child passes its animation up on mounted. Will investigate more though. Thanks for the help Link to comment Share on other sites More sharing options...
OSUblake Posted August 3, 2021 Share Posted August 3, 2021 2 hours ago, JayLow said: Selector utility looks promising. Docs say React and Angular refs though. Is it setup to work with Vue? It works with any element. The docs show React and Angular because the element isn't provided directly like it is with Vue (this.$el). 2 hours ago, JayLow said: I've believe I've tried the second option, but I've had cases where it will try to access the ref before it is defined. Do you have a demo of that? It might be because you need to wait until the $nextTick. Hard to say without seeing a demo. Link to comment Share on other sites More sharing options...
OSUblake Posted August 3, 2021 Share Posted August 3, 2021 1 hour ago, OSUblake said: It works with any element. The docs show React and Angular because the element isn't provided directly like it is with Vue (this.$el). Just added Vue to the docs. Link to comment Share on other sites More sharing options...
JayLow Posted August 5, 2021 Author Share Posted August 5, 2021 @OSUblake After a lot of testing, I think I got it working reliably. In cases where the child components mounted before the parent, the selector utility worked fine. However, I had cases where the opposite occured, and the mounted of the parent ran before any of the children, which led to nothing returning with the selector utility. I couldnt get $nextTick working reliably either. I had some cases where it worked fine, others where children were still rendering by the time it rain. What I ended up doing, was create a timeline on the parent component in its created() hook, and have each child pass up its tween in an $emit listener, which adds it to the parent timeline and kills the childs scrolltrigger. That way, children can work by themselves or be merged with a parent if its available. The parent sets up a scrolltrigger on its mounted() hook because thats when the DOM is available Example of child: props: { text: { type:String, required:true } }, mounted() { console.log('child mount') this.animation = split(this.$refs.text) this.$emit('child', this.animation) }, data() { return { animation:{} } }, Example of parent: export default { data() { return { timeline: null, childElements:[] }; }, methods: { fillTimeline(el) { this.timeline.add(el.progress(0).pause(0).delay(0).play(0), '<+=.3') }, addchild(anim) { anim.trigger.kill() anim.animation.pause(0) this.fillTimeline(anim.animation) } }, created() { this.timeline = timelineInit(); }, mounted() { timelineTrigger(this.$refs.trigger, this.timeline) } Link to comment Share on other sites More sharing options...
OSUblake Posted August 5, 2021 Share Posted August 5, 2021 10 minutes ago, JayLow said: In cases where the child components mounted before the parent, the selector utility worked fine. You should probably wait until the next tick. See if this works. If so, I'll add it to the selector docs. mounted() { this.$nextTick(() => { // everything should be rendered }); } Link to comment Share on other sites More sharing options...
JayLow Posted August 5, 2021 Author Share Posted August 5, 2021 4 minutes ago, OSUblake said: You should probably wait until the next tick. See if this works. If so, I'll add it to the selector docs. mounted() { this.$nextTick(() => { // everything should be rendered }); } No it does not work for me, selector utility comes back empty Link to comment Share on other sites More sharing options...
OSUblake Posted August 5, 2021 Share Posted August 5, 2021 Do you think you can put a simple demo of the problem on Codesandbox? I'd like to see if there's a way to fix it. Link to comment Share on other sites More sharing options...
JayLow Posted August 5, 2021 Author Share Posted August 5, 2021 36 minutes ago, OSUblake said: Do you think you can put a simple demo of the problem on Codesandbox? I'd like to see if there's a way to fix it. Apologies, I tried making a code sandbox demo. I structured it very similarly to my project, and works the right way on the sandbox, I'll have to look more into it Link to comment Share on other sites More sharing options...
OSUblake Posted August 5, 2021 Share Posted August 5, 2021 Hmm.... are you using Nuxt? Not sure what's going on because according to Vue's docs, the DOM should be ready in the next tick. Quote Note that mounted does not guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use vm.$nextTick inside of mounted: https://vuejs.org/v2/api/#mounted 1 Link to comment Share on other sites More sharing options...
JayLow Posted August 5, 2021 Author Share Posted August 5, 2021 Just now, OSUblake said: Hmm.... are you using Nuxt? Not sure what's going on because according to Vue's docs, the DOM should be ready in the next tick. https://vuejs.org/v2/api/#mounted I am using nuxt Link to comment Share on other sites More sharing options...
OSUblake Posted August 5, 2021 Share Posted August 5, 2021 It might be SSR that is messing up the rendering order. 1 Link to comment Share on other sites More sharing options...
OSUblake Posted August 5, 2021 Share Posted August 5, 2021 From Nuxt's docs. Quote Sometimes in server rendered pages $refs inside <client-only> might not be ready even with $nextTick, the trick might be to call $nextTick couple of times: https://nuxtjs.org/docs/2.x/features/nuxt-components That's not very specific. Just try it a couple of times. 🤦♂️ 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now